我在服务器内存模式下使用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
我尝试了不同的堆大小&amp;我停止了上面的代码 - 令人不安的是我总是看到我已插入大约13,800,000行 - 在服务器中有3GB可用堆 - 并且在终止上面的代码并且执行GC 0之后堆已满,堆需要2500MB -
这意味着每行占用大约180个字节 - 一个长的占用8个字节 - 因此这个重22倍。
这当然只是一个测试,真正的表通常只有一个字段 - 但我探讨的原因是当我尝试将1GB内存从oracle复制到HSQLDB时 - 在HSQLDB中它最终保持4GB ! (表结构相同)
现在,问题:
发生了什么事?我的测试看起来是否正确?
如何减少HSQLDB中的内存消耗?
如果没有简单的方法,其他类似的产品可能有合理的内存使用量?在这种情况下,H2怎么样?
谢谢
答案 0 :(得分:0)
最后我选择了H2,它占据了原始尺寸的1.2左右(在我的情况下)。它还具有额外的内存压缩模式。
答案 1 :(得分:-1)
这不是关系数据库的正确用例。您有一个只有一列的表,并存储一些长(BIGINT)值。您甚至没有主键,以便您搜索已插入的值。
这种用法甚至不需要HashMap。只需使用任何库中的HashSet实现。