2017-09-25 388 views
0

我正在運行Hibernate 4.1,並在Hikari池頂部運行Javassist運行時檢測程序,並在Oracle 12c之上運行。 JDK是1.7。Hibernate - SQL速度很快,但查詢速度仍然很慢

我有一個查詢,在數據庫上運行得非常快,並在Hibernate中獲取大約500個實體。根據JProfiler,查詢運行時間非常短,大​​約11毫秒,但總計Query.list運行大約7秒鐘。

我試過刪除所有過濾器,它顯示大部分時間都花在了Javaassist和其他與Hibernate相關的反射調用上(如AbstractProxyHandler等)。我讀到反射開銷應該很小,但看起來好像不是這樣,它看起來太多了。

請問您能告訴我什麼是瓶頸?

回答

0

確保您正在檢索的對象不具有以SELECT形式拖延獲取的子對象,而不是熱切地以JOIN形式提取。這可能會導致一種稱爲SELECT N + 1的行爲,其中Hibernate最終運行查詢以從其各自的表中獲取500個對象,然後爲每個對象獲取子對象的附加查詢。如果您有4或5個關係作爲每條記錄的SELECT語句獲取,並且您有500條記錄,突然間您會運行大約2000條查詢以獲取列表。

我建議打開Hibernate的SQL日誌記錄來查看它正在運行的查詢。如果在獲取列表時拋出一個非常長的SELECT查詢列表,請查看映射文件以查看您的關係是如何設置的。嘗試將它們調整爲fetch =「join」,並查看這些查詢是否消失以及性能是否提高。

這裏有一些可能相關的堆棧溢出問題,可能能夠提供更具體的細節。

Hibernate FetchMode SELECT vs JOIN

What is N+1 SELECT query issue?

別的東西需要注意分析器和這種性質的其他工具。通常,在追蹤性能問題時,特定的代碼塊會顯示爲最耗時的地方。人們傾向於跳到的共同結論是,所討論的代碼塊很慢。就你而言,你似乎將Hibernate的反射代碼視爲時間消耗的地方。考慮到這個代碼本身實際上可能並不慢,但是這是花費時間的地方,因爲由於算法複雜度而被頻繁地調用是非常重要的。我發現在很多問題中,序列化或反射出現會變慢,當現實是代碼被用來與外部資源進行通信時,並且該資源被稱爲1000次的時候,它應該只被稱爲一小撮。讓1000個查詢獲取您的列表將導致您的抽樣顯示在處理這些查詢的代碼中花費了大量時間。注意不要因爲代碼的設計/配置問題而導致經常調用的代碼很慢,這個問題很可能不在於hibernate使用反射,因爲反射通常不會在秒級上慢。

+0

我打開了SQL日誌記錄,它只有一個查詢,所有相關的集合都是連接獲取或未訪問。我的猜測是,反射可能不會很慢,但由於反射調用的次數,它會扭曲分析器結果。儘管如此,我仍然無法找到問題的根源,甚至將我的實體簡化爲最低限度。它基本上是兩個常規字段,幾個用戶類型字段,一個多對一集合,就是這樣。 –

相關問題