Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用hibernate读取300万条记录_Java_Sql_Hibernate_Select - Fatal编程技术网

Java 使用hibernate读取300万条记录

Java 使用hibernate读取300万条记录,java,sql,hibernate,select,Java,Sql,Hibernate,Select,我是hibernate中的noob,我必须使用Java中的hibernate从DB2z/OS数据库读取200万条记录。(JDBC) 我的问题是,15万条记录之后,我的内存用完了 我听说过批处理等,但我只找到实际插入新记录的解决方案。我想做的是在ArrayList中读取这些记录以供进一步使用 所以我实际上只是选择数据库中的一行来减少数据: getEntityManager().createQuery("select t.myNumber from myTable t").getResultList

我是hibernate中的noob,我必须使用Java中的hibernate从DB2z/OS数据库读取200万条记录。(JDBC)

我的问题是,15万条记录之后,我的内存用完了

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

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

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

同样有趣的是,如果有更好的方法读取如此大量的记录(可能没有Hibernate?)

下面是使用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();    
}
inti=0;
整批=100;
List numList=getEntityManager().createQuery(“从myTable t中选择t.myNumber”).setFirstResult(i).setMaxResults(batch).getResultList();
while(numList.size()=批处理){
//工艺流程清单
i+=批次;
numList=getEntityManager().createQuery(“从myTable t中选择t.myNumber”).setFirstResult(i).setMaxResults(batch).getResultList();
}

Hibernate文档,您已经找到了堆的上限。查看此处,了解如何正确调整堆的大小:


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

您不应该将所有记录加载到内存中,而是成批处理它们,例如:使用 createQuery(…).setFirstResult(i*1000).setMaxResults(1000)

是的,偏离航线 您可以使用Apache™ Hadoop®适用于大型项目。它为可靠、可扩展、分布式计算开发开源软件。它被设计成从单个服务器扩展到数千台机器

这基本上是您正在处理的问题的设计问题。忘记Hibernate,即使您在普通JDBC中做同样的事情,您也会遇到内存问题,可能会晚一点。加载如此巨大的数据并将其保存在内存中的想法不适用于要求短请求-响应周期的应用程序,也不利于可伸缩性。正如其他人所建议的那样,您可以尝试批处理或分页行为,或者如果您想变得更加奇特,您可以尝试通过分布式数据网格(like)或map reduce框架进行并行处理

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


有一些类似springbatch的框架,它们通过将工作划分为块(批处理),然后逐个处理来解决这些问题。它甚至内置了基于JPA的,并在批处理中执行此工作。

最好的方法是使用无状态会话(不处理缓存)和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();
    }

您不应该在内存中加载那么多记录。您应该分批执行,即加载一批100个(取决于)并进行处理,然后再读取下一批100个。请尝试阅读以下内容:a)即使是稍大的行集也不要使用hibernate;b)使用原始SQL和光标滚动结果,因此一次内存中只有一行