确定 MariaDB 中十进制数据类型列所需的精度和小数位数

问题描述 投票:0回答:1

我有大量的 MariaDB 10.6 表,其中有几个

decimal(P,D)
列和数百万行。这些列的精度(
P
)和规模(
D
)曾经被设置为不切实际的高水平,只是容纳每个可能的输入,例如
decimal(24,10)

现在我想根据这些表中的实际数据确定所需的

P
D
值。

我能想到的最好的办法是

SELECT CEIL(LOG10(MAX(col))) AS maxI,
       MAX(CEIL(LOG10(CAST(REVERSE(SUBSTR(CAST(col % 1 AS VARCHAR(12)), 3)) AS INT)))) AS maxD
FROM tbl;

其中

col
是数据类型为
decimal(24,10)
的列,
maxI
是最大整数部分,
maxP
是小数点后有效位数的最大数量(因此
maxP = maxI + maxD
)。

虽然它确实有效,但速度慢得不足为奇,我想知道是否有更有效的方法来实现这一目标。

mariadb decimal precision
1个回答
0
投票

处理精度数字时不要使用双精度函数(如 LOG10),以避免警告和舍入错误。

计算小数点前的最大位数非常简单,因为这可以由优化器处理而无需触及索引。对于无符号小数,您可以使用

MAX()
,对于有符号小数,您必须使用
MIN()
MAX()

select @maxI1:=LENGTH(TRUNCATE(MIN(col1),0)), @maxI2:=LENGTH(TRUNCATE(MAX(col1),0)) FROM tbl;

小数位数最多的有记录

MAX(col1 - TRUNCATE(col1,0))
。 所以第二条语句是:

SELECT IF(@maxI1 > @maxI2, @maxI1, @maxI2) as maxI,
       LENGTH(MAX(col1 - TRUNCATE(col1, 0))) -2 as maxD
FROM tbl;

速度对比(7 Mio 行):

SELECT CEIL(LOG10(MAX(col1))) AS maxI, MAX(CEIL(LOG10(CAST(REVERSE(SUBSTR(CAST(col1 % 1 AS VARCHAR(12)), 3)) AS INT)))) AS maxD FROM tbl;
+------+------+
| maxI | maxD |
+------+------+
|   13 |   10 |
+------+------+
1 row in set, 40964 warnings (6.166 sec)

SELECT @maxI1:=LENGTH(TRUNCATE(MIN(col1),0)) as maxI1, @maxI2:=LENGTH(TRUNCATE(MAX(col1),0)) as maxI2 FROM tbl;
+-------+-------+
| maxI1 | maxI2 |
+-------+-------+
|     5 |    13 |
+-------+-------+
1 row in set (0.000 sec)

SELECT IF(@maxI1 > @maxI2, LENGTH(@maxI1), LENGTH(@maxI2)) as maxI, LENGTH(MAX(col1 - truncate(col1, 0))) -2 as maxD FROM tbl;
+------+------+
| maxI | maxD |
+------+------+
|   13 |   10 |
+------+------+
1 row in set (4.168 sec)
© www.soinside.com 2019 - 2024. All rights reserved.