2014-11-20 61 views
1

我使用休眠,我想执行这个查询:setMaxResults巨大的表占用内存过多

SELECT s.executionTime, g.date, s.name 
FROM SimulationStatsGroup g 
LEFT JOIN SimulationStats s ON s.group_id = g.id 
WHERE g.name = 'general' 
ORDER BY g.date DESC 
LIMIT 30 

在此查询我要表和1 SimulationStatsGroup包含几个SimulationStats

然而,随着HQLLIMIT生成一个错误,因为休眠不支持它。 所以我用setMaxResults(int)来代替,但是当我在日志中查找查询时,我可以看到根本没有LIMIT

这可能是因为休眠知道一个SimulationStatsGroup可以包含多个SimulationStats,因此它知道限制到30周的结果将不会返回30 SimulationStatsGroup通缉,但30行,这会给我3 SimulationStatsGroup如果我们假设有10 。

所以,我可以理解为什么它是这样工作,而不是我想要的。但是,这种执行查询的方式会让我的应用程序崩溃,因为它使用了太多的内存,因为我的表中有超过100万行,看起来休眠正试图将所有行放入列表中。

我的问题是:有没有办法限制使用内存来保持我的应用程序活着,只保留我的30个对象?

+0

请附上您的实际代码。 – 2014-11-21 00:03:37

+0

我猜休眠可能会让你懒洋洋地加载模拟状态。另请说明如何将实体映射到表格。我的意思是,我认为hibernate会首先执行查询,然后才会创建对象并填充它们的值(不确定,但它对我来说很有意义),所以你可能不得不告诉hibernate默认不加载你的统计信息。 – Leo 2014-11-21 00:09:49

+0

默认情况下,Postgres驱动程序将完整结果缓存在内存中。你可以通过JDBC API来改变它,但我不知道你是否可以通过Hibernate来实现:http://jdbc.postgresql.org/documentation/93/query.html – 2014-11-21 07:21:55

回答

2

对于非常大的表,我建议您使用the seek method,但它需要运行原生查询,并且每个数据库都有自己的限制行数的方法。

你的情况,你可以简单地运行两个查询,而不是一个:

  • 第一个查询只返回父IDS:

    Session session = sessionFactory.openSession(); 
    Query query = session.createQuery("select ssg.id from SimulationStatsGroup ssg"); 
    query.setFirstResult(0); 
    query.setMaxResults(10); 
    List<Long> ids = query.list(); 
    
  • 那么你可以使用第二个查询获取带孩子的父母:

    Session session = sessionFactory.openSession(); 
    Query query = session.createQuery("select ssg from SimulationStatsGroup ssg left join fetch ssg.simulationStats where ssg.id in (:ids) "); 
    query.setParameterList("ids", ids); 
    List<SimulationStatsGroup> simulationStatsGroups = query.list(); 
    

这样你可以绕过Hibernate内存中的父子分组限制。

+0

我从来没有想过使用这样的2个查询。这工作正常,谢谢! – 2014-11-21 15:07:47