【发布时间】:2014-05-05 22:52:17
【问题描述】:
我在服务器内存模式下使用 hsqldb 2.3.2。 我遇到的情况是,我向 hsqldb 插入一些信息,并且 HSQLDB 使用的堆空间(即使在 GC 之后)比我将它保存在 java 堆中的普通 HashMap/LinkedList 中大 3 到 4。
以下是将多条记录插入到内存中的 hsqldb 服务器的代码:
Connection c = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost","sa","");
c.setAutoCommit(false);
PreparedStatement ps = c.prepareStatement("set database sql syntax ora true");
ps.execute();
ps.close();
ps = c.prepareStatement("create table t (x long)");
ps.execute();
ps.close();
c.close();
String x = "insert into t values(?)";
c = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost","sa","");
c.setAutoCommit(false);
ps = c.prepareStatement(x);
for(int i=0;i<1000*1000*10000;i++){
long z = new Random().nextLong();
ps.setLong(1, z);
ps.addBatch();
if(i%1000==0){
ps.executeBatch();
ps.clearParameters();
ps.clearBatch();
ps.close();
ps = null;
ps = c.prepareStatement(x);
}
c.commit();
c.close();
if(i%100000 == 0){
System.out.println(i);//print number of rows inserted
c.commit();
c.close();
c = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost","sa","");
c.setAutoCommit(false);
ps = c.prepareStatement(x);
}
}
我使用 JVisutalVM 跟踪服务器 HSQLDB 进程,并 我一直运行上面的代码,直到 OutOfMemory 发生
我尝试了不同的堆大小并停止了上面的代码 - 令人不安的是我总是看到我已经插入了大约 13,800,000 行 - 在具有 3GB 可用堆的服务器中 - 并且在终止上面的代码并执行 GC 后堆已满0 堆占用 2500MB -
这意味着每一行占用大约 180 个字节 - 一个 long 占用 8 个字节 - 所以要重 22 倍。
这当然只是一个测试,真正的表通常不会只有一个字段 - 但我探索这个的原因是当我尝试将 1GB 的内存从 oracle 复制到 HSQLDB 时 - 在 HSQLDB 中它最终持有 4GB ! (表结构相同)
现在,问题:
发生了什么事?我的测试看起来正确吗?
如何减少 HSQLDB 中的内存消耗?
如果没有简单的方法,还有哪些类似的产品可能有合理的内存使用? H2 在这种情况下如何?
谢谢
【问题讨论】: