2014-11-20 3 views
1

Я использую Hibernate, и я хотел бы выполнить этот запрос: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.

Однако, с HQL, LIMIT генерирует ошибку, потому что спящий режим не поддерживает его. Вместо этого я использовал setMaxResults(int), но когда я ищу запрос в журналах, я вижу, что нет LIMIT.

Это, вероятно, потому, что Hibernate знает, что SimulationStatsGroup может содержать несколько SimulationStats, таким образом, он знает, что ограничение 30 результатов не будет возвращать 30 SimulationStatsGroup, как хотелось, но 30 рядов, которые дадут мне 3 SimulationStatsGroup, если предположить, что существует составляют 10 SimulationStats в 1 SimulationStatsGroup.

Итак, я могу понять, почему он работает таким образом, а не как мне хотелось бы. Но этот способ выполнения запроса приводит к сбою моего приложения, потому что он использует слишком много памяти, потому что у меня в моих таблицах больше 1 миллиона строк, и кажется, что Hibernate пытается поместить все строки в список.

Мой вопрос: есть ли способ ограничить использование памяти для сохранения моего приложения и сохранения только моих 30 объектов?

+0

Пожалуйста, укажите ваш фактический код. –

+0

Я думаю, что спящий режим может позволить вам загружать SimulationStats лениво. Также укажите, как вы сопоставляете свои объекты с таблицами. Я имею в виду, я думаю, что hibernate сначала выполнит запрос, и только после этого он создаст объекты и заполнит их значениями (не уверен, но это имеет смысл для меня), поэтому вам, возможно, придется сказать, что hibernate не загружает статистику по умолчанию , – Leo

+0

По умолчанию драйвер Postgres выполняет буферизацию полного результата в памяти. Вы можете изменить это через JDBC API, но я не знаю, можете ли вы это сделать через Hibernate: http://jdbc.postgresql.org/documentation/93/query.html –

ответ

2

Для очень большой таблицы я предлагаю вам использовать the seek method, но для этого требуется выполнение собственных запросов, и каждая база данных имеет собственный способ ограничения номера строк.

В вашем случае вы можете просто запустить два запроса вместо одного:

  • первый запрос просто возвращают родительские идентификаторы:

    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 таких запросов , Это прекрасно работает, спасибо! –

Смежные вопросы