2014-06-23 50 views
7

我使用運行在linux服務器上的java編碼服務器端應用程序。 我使用hibernate打開會話到數據庫,使用本機sql來查詢它,並總是通過try,catch,最後關閉這個會話。使用休眠時的內存使用率高

我的服務器查詢數據庫使用休眠與非常高的頻率。

我已經定義MaxHeapSize爲3000M,但它通常在RAM上使用2.7GB,它可以減少但比增加慢。有時它會增長到3.6GB的內存使用量,超過我的MaxHeapSize定義時啓動。

當使用的內存是3.6GB時,我嘗試使用-jmap命令轉儲它並獲得了一個大小爲1.3GB的heapdump。

即時通訊使用的Eclipse MAT來分析它,這裏是從MAT Dominator tree 支配樹我覺得休眠的問題,我有這麼多org.apache.commons.collections.map.AbstractReferenceMap $ ReferenceEntry這樣。它可能不能被垃圾收集處理或可以緩慢。

我該如何解決?

回答

10

您在您的IN查詢列表中有250k條目。即使是本地查詢也會使數據庫癱瘓。由於性能原因,Oracle將IN查詢列表限制爲1000,因此您應該這樣做。

給予更多內存不會解決問題,您需要使用分頁將選擇/更新限制爲最多1000個條目的批次。

Streaming is an option,但是,對於如此大的結果集,keyset pagination通常是最佳選擇。

如果您可以執行數據庫中的所有處理,那麼您不必將250k條記錄從數據庫移動到應用程序。爲什麼很多RDBMS提供高級過程語言(例如PL/SQL,T-SQL)是有很好的理由的。

+0

你能教我多一點嗎?我幾乎沒有關於Oracle數據庫交互的經驗。 – Viet

+1

您需要獲取N個條目,更新它們,然後獲取下一批,等等。 –

+0

我仍然困惑,在我的查詢「更新..在哪裏..在(...)」,在查詢列表很小,它不能達到1000 當我在Eclipse MAT來支配樹的葉子展開,我覺得我的選擇查詢(‘sqlQueryCheckSet’在我的代碼),許多的它,我只是想它 – Viet

1

謝謝Vlad Mihalcea與您的鏈接Hibernate issue,這是hibernate的bug,它修復了3.6版。我只是更新我的休眠版本3.3.2到版本3.6.10,使用默認值「hibernate.query.plan_cache_max_soft_references」(2048),「hibernate.query.plan_cache_max_strong_references」(128),我的問題已經消失。沒有更多的高內存使用。

3

請注意,儘管queryPlanCache中的對象數量可以配置和限制,但這可能不正常。

在我們的例子中,我們正在寫在HQL類似查詢到這一點:

hql = String.format("from Entity where msisdn='%s'", msisdn); 

這導致了N個不同的查詢要去queryPlanCache。在改變了這個查詢:

hql = "from Blacklist where msisnd = :msisdn"; 
... 
query.setParameter("msisdn", msisdn); 

queryPlanCache的大小急劇從100兆減少至幾乎爲0。此第二查詢被轉換爲所產生的高速緩衝存儲器內只是一個對象的一個​​單一preparedStament。