gpt4 book ai didi

sql - h2默认DECIMAL精度性能

转载 作者:行者123 更新时间:2023-12-03 02:13:22 24 4
gpt4 key购买 nike

当我使用默认精度设置创建 DECIMAL 列时,在 H2 Web 控制台中,该列被定义为 DECIMAL(65535, 32767),命令“show columns from .. ."给我 DECIMAL(65535)

H2 中的 Decimal 数据类型映射到 BigDecimal (来自 H2 文档),但我不确定 H2 如何处理它。

如果我使用较小的精度,性能是否会提高?

最佳答案

要了解有关 H2 的 DECIMAL 数据类型的更多信息,请检查 h2-x.y.z.jar 附带的 org.h2.value.ValueDecimal.

仔细观察,您会发现默认值如您所提到的:

/** The default precision for a decimal value. */
static final int DEFAULT_PRECISION = 65535;
/** The default scale for a decimal value. */
static final int DEFAULT_SCALE = 32767;

仔细观察ValueDecimal:

private final BigDecimal value;

org.h2.store.Data:

public Value readValue() {
...
case Value.DECIMAL: {
int scale = readVarInt();
int len = readVarInt();
byte[] buff = DataUtils.newBytes(len);
read(buff, 0, len);
BigInteger b = new BigInteger(buff);
return ValueDecimal.get(new BigDecimal(b, scale));
}

您可以看到DECIMAL只不过是BigDecimal。也就是说,您在使用 java.math.BigDecimal 时将面临的所有性能问题,在使用 DECIMAL 时都会面临。

如果您真的很喜欢它,您可以进一步研究该类(class),看看精度/比例发挥的确切作用。

如果我们查看文档,所有 H2 关于 DECIMAL 数据类型和性能的说法是:

The DECIMAL/NUMERIC type is slower and requires more storage than the REAL and DOUBLE types.

所以他们说这是事实。

但是既然你谈论的是性能,我们可以切入主题并做一些测试。测试类的代码如下,让我们看看输出/结果:

TYPE              INSERT time    COUNT() time   .db Size (kb)  
DECIMAL(20,2) 6.978 0.488 27958.0
DECIMAL(100,2) 4.879 0.407 25648.0
DECIMAL(100,80) 8.794 0.868 90818.0
DECIMAL(60000,2) 4.388 0.4 25104.0
DECIMAL(1000,900) 112.905 6.549 1016534.0
REAL 5.938 0.318 22608.0
DOUBLE 6.985 0.416 25088.0

正如您所看到的,当精度改变时,时间或存储大小没有明显变化(精度20大约需要与60000一样多的时间/大小! )。

问题是当你改变比例时。这是你应该担心的;如您所见,DECIMAL(100,2)DECIMAL(100,80) 显示时间和存储空间都有很大增加。

DECIMAL(1000,900) 需要超过 1 GB(!!!) 来存储完全相同的值。

最后,在上面的测试中,REALDOUBLE 似乎并不比 DECIMAL 好多少(它们甚至可能看起来更差)。但尝试更改插入的行数(测试方法中的 for 循环),数字越大,它们似乎响应越好。

* DECIMAL(20,2) 似乎比其他的慢/大。那不是真的。实际上,无论您选择先运行什么,都会稍微慢一些/更大一些。想想看...

public class Main {
public static void main(String[] a) throws Exception {
Class.forName("org.h2.Driver");
System.out.format("%-18s%-15s%-15s%-15s", "TYPE", "INSERT time", "COUNT() time", ".db Size (kb)");
System.out.println();
testPerformance("TEST_DECIMAL_20_2", "DECIMAL(20,2)");
testPerformance("TEST_DECIMAL_100_2", "DECIMAL(100,2)");
testPerformance("TEST_DECIMAL_100_80", "DECIMAL(100,80)");
testPerformance("TEST_DECIMAL_60000_2", "DECIMAL(60000,2)");
testPerformance("TEST_DECIMAL_1000_900", "DECIMAL(1000,900)");
testPerformance("TEST_REAL", "REAL");
testPerformance("TEST_DOUBLE", "DOUBLE");
}

private static void testPerformance(String dbName, String type) throws SQLException {
System.out.format("%-18s", type);
Connection conn = DriverManager.getConnection("jdbc:h2:" + dbName, "sa", "");
conn.createStatement().execute("DROP TABLE IF EXISTS TEST;");
conn.createStatement().execute("CREATE TABLE TEST (DECTEST " + type +" )");
long insertStartTime = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
conn.createStatement().execute("INSERT INTO TEST (DECTEST) VALUES (12345678901234.45)");
}
double insertTime = ((double)(System.currentTimeMillis()-insertStartTime))/1000;
System.out.format("%-15s", insertTime+"");
long countStartTime = System.currentTimeMillis();
conn.createStatement().executeQuery("select COUNT(DECTEST) from TEST");
double countTime = ((double)(System.currentTimeMillis()-countStartTime))/1000;
System.out.format("%-15s", countTime+"");
conn.close();
double fileSize = (double)new File(dbName+".h2.db").length() / 1024;
System.out.format("%-15s", fileSize+"");
System.out.println();
}
}

关于sql - h2默认DECIMAL精度性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16274887/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com