Hibernate性能優化技巧

在進行Hibernate性能優化時,須要從如下幾個方面進行考慮:sql

數據庫設計調整。數據庫

HQL優化。緩存

API的正確使用(如根據不一樣的業務類型選用不一樣的集合及查詢API)。性能優化

主配置參數(日誌、查詢緩存、fetch_size、batch_size等)。session

映射文件優化(ID生成策略、二級緩存、延遲加載、關聯優化)。併發

一級緩存的管理。數據庫設計

針對二級緩存,還有許多特有的策略。性能

事務控制策略。fetch

數據的查詢性能每每是影響一個應用系統性能的主要因素。對查詢性能的影響會涉及到系統軟件開發的各個階段,例如,良好的設計、正確的查詢方法、適當的緩存都有利於系統性能的提高。大數據

系統性能的提高設計到系統中的各個方面,是一個相互平衡的過程,須要在應用的各個階段都要考慮。而且在開發、運行的過程當中要不斷地調整和優化才能逐步提高系統的性能。

設計階段的考慮問題

一個良好的數據庫結構有利於系統性能的提高。這裏所說的良好結構的數據庫並不單純是指知足數據庫設計範式的數據庫結構。這是由於,按照數據庫範式所設計的數據庫只能說在結構上是最優的,沒有冗餘數據等問題,但在生產過程當中並不必定能得到最佳的性能。有時候適當地增長一些數據的冗餘雖然增長了數據維護的難度,但能夠極大地簡化業務的查詢,提升數據檢索的效率。

在使用Java訪問數據庫的時候,還存在另一個問題,就是面向對象的Java語言與關係型數據庫之間的矛盾。在這二者之間必然要涉及到一個相互轉化的問題,對於這個問題是否可以正確的處理也是影響系統性能的一個重要因素。

綜合以上提出的各類問題,在數據庫設計階段要綜合考慮如下三個方面的因素。

Java建模

在創建Java對象模型的時候,要考慮數據庫持久化的方便性,所創建的Java對象模型應該能夠很容易地被數據所存儲,而且數據庫中表的結構也是越簡單越好。

數據庫結構

在設計數據庫結構的時候也要考慮到是否能夠很容易地用Java對象去表示。這裏並非簡單的一個表對應一個對象的直接轉換,更重要的是轉換後的Java對象應該可以描述出數據間的關係。

因此在設計階段,對於Java對象和數據庫結構要進行綜合考慮,也就是能夠從兩個方向進行考慮,畢竟二者之間不是一個時代的產物,設計的結果應該在二者之間達到一個平衡,雖然不能每一方都達到最優,但也不能形成有一方結構不好的狀況。就像裝水的木桶,最矮的板子決定水桶的容量。

業務需求

前面兩個因素都是純技術方面的考慮,在設計的過程當中,更重要的是要緊扣業務需求。這是由於任何的軟件系統都是以業務爲中心的,那麼對於系統的設計也不例外,在設計的階段就應該考慮業務實現的方便性以及執行的效率。一個良好的結構設計不但使業務功能的實現變得很是容易而且能夠避免不少複雜的操做,還能夠達到提高系統性能的目的。

設計階段是整個應用系統開發中的根基,其對軟件的影響僅次於對系統需求的把握。因此在設計階段應該對整個軟件系統有一個總體的考慮,這裏所說的具體設計也只是設計階段中的不多的一部分,綜合考慮多方面的因素才能達到更佳的性能。

 

文章分爲十三個小塊兒對Hibernate性能優化技巧進行總結性分析,分析以下:

1、在處理大數據量時,會有大量的數據緩衝保存在Session的一級緩存中,這緩存大太時會嚴重顯示性能,因此在使用Hibernate處理大數據量的,可使用session. clear()或者session. evict(Object) 在處理過程當中,清除所有的緩存或者清除某個對象。

2、對大數據量查詢時,慎用list()或者iterator()返回查詢結果,

<1>. 使用List()返回結果時,Hibernate會全部查詢結果初始化爲持久化對象,結果集較

大時,會佔用不少的處理時間。

<2>. 而使用iterator()返回結果時,在每次調用iterator.next()返回對象並使用對象時,

Hibernate才調用查詢將對應的對象初始化,對於大數據量時,每調用一次查詢都會花

費較多的時間。當結果集較大,可是含有較大量相同的數據,或者結果集不是所有都會

使用時,使用iterator()纔有優點。

<3>. 對於大數據量,使用qry.scroll()能夠獲得較好的處理速度以及性能。並且直接對結

果集向前向後滾動。

3、對於關聯操做,Hibernate雖然能夠表達複雜的數據關係,但請慎用,使數據關係較爲

簡單時會獲得較好的效率,特別是較深層次的關聯時,性能會不好。

4、對含有關聯的PO(持久化對象)時,若default-cascade="all"或者 「save-update」,新增PO時,請注意對PO中的集合的賦值操做,由於有可能使得多執行一次update操做。

5、在一對多、多對一的關係中,使用延遲加載機制,會使很多的對象在使用時纔會初始化,這樣可以使得節省內存空間以及減小數據庫的負荷,並且若PO中的集合沒有被使用時,就可減小互數據庫的交互從而減小處理時間。

6、對於大數據量新增、修改、刪除操做或者是對大數據量的查詢,與數據庫的交互次數是決定處理時間的最重要因素,減小交互的次數是提高效率的最好途徑,因此在開發過程當中,請將show_sql設置爲true,深刻了解Hibernate的處理過程,嘗試不一樣的方式,可使得效率提高。

7、Hibernate是以JDBC爲基礎,可是Hibernate是對JDBC的優化,其中使用Hibernate的緩衝機制會使性能提高,如使用二級緩存以及查詢緩存,若命中率較高明,性能會是到大幅提高。

8、Hibernate能夠經過設置hibernate.jdbc.fetch_size,hibernate.jdbc.batch_size等屬性,對Hibernate進行優化。

9、不過值得注意的是,一些數據庫提供的主鍵生成機制在效率上未必最佳,大量併發insert數據時可能會引發表之間的互鎖。數據庫提供的主鍵生成機制,每每是經過在一個內部表中保存當前主鍵狀態(如對於自增型主鍵而言,此內部表中就維護着當前的最大值和遞增量),以後每次插入數據會讀取這個最大值,而後加上遞增量做爲新記錄的主鍵,以後再把這個新的最大值更新回內部表中,這樣,一次Insert操做可能致使數據庫內部屢次表讀寫操做,同時伴隨的還有數據的加鎖解鎖操做,這對性能產生了較大影響。所以,對於併發Insert要求較高的系統,推薦採用uuid.hex 做爲主鍵生成機制。

10、Dynamic Update 若是選定,則生成Update SQL 時不包含未發生變更的字段屬性,這樣能夠在必定程度上提高SQL執行效能.Dynamic Insert 若是選定,則生成Insert SQL 時不包含未發生變更的字段屬性,這樣能夠在必定程度上提高SQL執行效能

11、在編寫代碼的時候請,對將POJO的getter/setter方法設定爲public,若是設定爲private,Hibernate將沒法對屬性的存取進行優化,只能轉而採用傳統的反射機制進行操做,這將致使大量的性能開銷(特別是在1.4以前的Sun JDK版本以及IBM JDK中,反射所帶來的系統開銷至關可觀)。

12、在one-to-many 關係中,將many 一方設爲主動方(inverse=false)將有助性能的改善。

十3、因爲多對多關聯的性能不佳(因爲引入了中間表,一次讀取操做須要反覆數次查詢),所以在設計中應該避免大量使用。

還能夠看看Struts與Hibernate的完美結合方案