用hibernate读取300万条记录

时间:2014-07-01 07:54:22

标签: java sql hibernate select

我是hibernate中的菜鸟,我必须使用Java中的hibernate从DB2 z / OS-Database中读取200万条记录。 (JDBC)

我的问题是,我在150000条记录后运行OutOfMemory。

我听说过批处理等,但我只找到实际插入新记录的解决方案。我想要做的是在ArrayList中读取此记录以供进一步使用。

所以我实际上只是选择数据库的一行来减少数据:

getEntityManager().createQuery("select t.myNumber from myTable t").getResultList();

同样有趣的是,如果有更好的方法来阅读如此大量的记录。(也许没有Hibernate?)

6 个答案:

答案 0 :(得分:6)

以下是使用hibernate进行批处理的方法。请记住,这不是100%测试。它是一种伪逻辑。

int i=0;
int batch = 100;
List<myNumber> numList = getEntityManager().createQuery("select t.myNumber from myTable t").setFirstResult(i).setMaxResults(batch).getResultList();

while(numList.size() == batch){
    //process numList
    i+=batch;
    numList = getEntityManager().createQuery("select t.myNumber from myTable t").setFirstResult(i).setMaxResults(batch).getResultList();    
}

setFirstResult()setMaxResults()

的Hibernate文档

答案 1 :(得分:1)

您不应将所有记录加载到内存中,而是批量处理它们,例如:使用循环每1000条记录 。的createQuery(...)setFirstResult(I * 1000).setMaxResults(1000);

答案 2 :(得分:1)

最好的方法是使用statelableSession(不处理缓存)和使用scrollableResults方法的批量操作:

StatelessSession statelessSession = sessionFactory.openStatelessSession(connection);
    try {
     ScrollableResults scrollableResults = statelessSession.createQuery("from Entity").scroll(ScrollMode.FORWARD_ONLY);

     int count = 0;
     while (scrollableResults.next()) {
      if (++count > 0 && count % 100 == 0) {
       System.out.println("Fetched " + count + " entities");
      }
      Entity entity = (Entity) scrollableResults.get()[0];
      //Process and write result
     }
    } finally {
     statelessSession.close();
    }

答案 3 :(得分:0)

您已找到堆的上限。看看这里知道如何正确调整堆大小:

Increase heap size in Java

然而,我无法想象为什么你需要在内存中拥有300万条记录的列表。也许有了更多信息,我们可以为您的算法找到替代解决方案吗?

答案 4 :(得分:0)

是偏离正确的 您可以将Apache™Hadoop®用于大型项目。它开发了用于可靠,可扩展的分布式计算的开源软件。它旨在从单个服务器扩展到数千台计算机 hadoop apache

答案 5 :(得分:0)

这基本上是您正在处理的问题的设计问题。忘记Hibernate,即使你在普通的JDBC中做同样的事情,你也会遇到内存问题,也许有点晚了。加载如此庞大的数据并保留在内存中的想法不适合需要较短请求 - 响应周期的应用程序,也不利于可伸缩性。正如其他人建议您可以尝试批处理或分页行为,或者如果您想要更具异国情调,您可以尝试通过分布式数据网格(如Infinispan)或map {reduce框架Hadoop进行并行处理。

根据您的问题描述,您似乎需要将数据保存在内存中。 如果必须将大量数据保存在内存中,那么您可以批量查询数据并将其存储在分布式缓存(如Infinispan)中,该缓存可以跨越单个机器上的多个JVM或形成群集的多个机器。这样,您的数据将部分驻留在每个节点上。这些Infinispan可以用作分布式缓存。

像Spring Batch这样的框架通过将工作分成块(批处理)然后逐个处理它们来解决这些问题。它甚至还内置了基于JPA的readerswriters,可以批量执行此工作。