setMaxResults 与大型表使用太多内存



我正在使用Hibernate,我想执行这个查询:

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

但是,对于 HQL,LIMIT会生成错误,因为休眠不支持它。所以我改用了setMaxResults(int),但是当我在日志中查找查询时,我可以看到根本没有LIMIT

这可能是因为 Hibernate 知道一个SimulationStatsGroup可以包含多个SimulationStats,因此它知道限制为 30 个结果不会按需要返回 30 SimulationStatsGroup而是 30 行,如果我们假设 10 SimulationStats在 1 SimulationStatsGroup中有 10 行,这将给我 3 SimulationStatsGroup

所以,我可以理解为什么它以这种方式工作,而不是我想要的方式。但是,这种执行查询的方式使我的应用程序崩溃,因为它占用了太多内存,因为我的表中有超过 100 万行,而且似乎 Hibernate 正在尝试将所有行放在一个列表中。

我的

问题是:有没有办法限制内存的使用来保持我的应用程序处于活动状态并只保留我的 30 个对象?

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

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

  • 第一个查询仅返回父 ID:

    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();
    

这样,您可以绕过休眠内存中父子分组限制。

最新更新