2014-11-20 38 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