当我使用默认精度设置创建DECIMAL
列时,在H2网络控制台中,此列定义为DECIMAL(65535, 32767)
,命令“显示来自...的列”给我DECIMAL(65535)
。< / p>
H2中的十进制数据类型映射到BigDecimal
(来自H2文档),但我不确定H2如何处理它。
如果我使用较小的精度,是否有任何性能提升?
答案 0 :(得分:3)
要了解有关H2的DECIMAL
数据类型的更多信息,请检查org.h2.value.ValueDecimal
附带的h2-x.y.z.jar
类。
仔细看看,您会看到默认值如您所述:
/** 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
。
如果你真的喜欢它,你可以进一步学习课程,看看精确度/音阶的确切作用。
如果我们转到文档,所有H2都会说DECIMAL
数据类型和性能是:
DECIMAL
/NUMERIC
类型较慢,需要的存储量超过REAL
和DOUBLE
类型。
所以他们说这是事实。
但是既然你在谈论表现,我们可以切入追逐并做一些测试。测试类的代码如下,让我们得到输出/结果:
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千兆字节(!!!)才能存储完全相同的值。
最后,在上面的测试中,REAL
和DOUBLE
似乎没有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();
}
}
答案 1 :(得分:3)
DECIMAL
的精度和比例在H2中是可选的。如果在不指定精度/比例的情况下创建列,则性能不受影响,存储不受影响,您可以插入任何值并返回相同的值:
create table test(data decimal);
insert into test values(1.345);
select * from test;
> 1.345