【问题标题】:Hsqldb - memory overuse?Hsqldb - 内存过度使用?
【发布时间】: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 ! (表结构相同)

现在,问题:

  1. 发生了什么事?我的测试看起来正确吗?

  2. 如何减少 HSQLDB 中的内存消耗?

  3. 如果没有简单的方法,还有哪些类似的产品可能有合理的内存使用? H2 在这种情况下如何?

谢谢

【问题讨论】:

    标签: java hsqldb h2


    【解决方案1】:

    最后我选择了 H2,它占据了原始大小的 1.2 左右(在我的例子中)。它还具有额外的内存压缩模式。

    【讨论】:

      【解决方案2】:

      这不是关系数据库的正确用例。您有一个只有一列的表,并且正在存储一些长 (BIGINT) 值。你甚至没有一个主键来允许你搜索你插入的值。

      这种用法甚至不需要 HashMap。只需使用任何库中的 HashSet 实现即可。

      【讨论】:

      • 就像我写的那样——我有一个实际案例,带有真正的索引表——它需要 4 到 5 倍的时间。长场示例就是证明。最后我选择了 H2,它占据了原始大小的 1.2 左右(在我的例子中)。它还具有额外的内存压缩模式。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-26
      • 1970-01-01
      • 2012-03-08
      • 2014-09-14
      • 2014-03-30
      • 2016-07-29
      • 1970-01-01
      相关资源
      最近更新 更多