Hibernate程式效能優化的考慮要點

2021-04-19 02:48:09 字數 3686 閱讀 8193

初用hibernate的人也許都遇到過效能問題,實現同一功能,用hibernate與用jdbc效能相差十幾倍很正常,如果不及早調整,很可能影響整個專案的進度。

大體上,對於hibernate效能調優的主要考慮點如下:

◆資料庫設計調整

◆hql優化

◆api的正確使用(如根據不同的業務型別選用不同的集合及查詢api)

◆主配置引數(日誌,查詢快取,fetch_size, batch_size等)

◆對映檔案優化(id生成策略,二級快取,延遲載入,關聯優化)

◆一級快取的管理

◆針對二級快取,還有許多特有的策略

◆事務控制策略

1、資料庫設計

a) 降低關聯的複雜性

b) 盡量不使用聯合主鍵

c) id的生成機制,不同的資料庫所提供的機制並不完全一樣

d) 適當的冗餘資料,不過分追求高正規化

2、hql優化

hql如果拋開它同hibernate本身一些快取機制的關聯,hql的優化技巧同普通的sql優化技巧一樣,可以很容易在網上找到一些經驗之談。

3、主配置

a) 查詢快取,同下面講的快取不太一樣,它是針對hql語句的快取,即完全一樣的語句再次執行時可以利用快取資料。但是,查詢快取在乙個交易系統(資料變更頻繁,查詢條件相同的機率並不大)中可能會起反作用:它會白白耗費大量的系統資源但卻難以派上用場。

b) fetch_size,同jdbc的相關引數作用類似,引數並不是越大越好,而應根據業務特徵去設定

c) batch_size同上。

d) 生產系統中,切記要關掉sql語句列印。

4、快取

a) 資料庫級快取:這級快取是最高效和安全的,但不同的資料庫可管理的層次並不一樣,比如,在oracle中,可以在建表時指定將整個表置於快取當中。

b) session快取:在乙個hibernate session有效,這級快取的可干預性不強,大多於hibernate自動管理,但它提供清除快取的方法,這在大批量增加/更新操作是有效的。比如,同時增加十萬條記錄,按常規方式進行,很可能會發現outofmemeroy的異常,這時可能需要手動清除這一級快取:session.evict以及session.clear

c) 應用快取:在乙個sessionfactory中有效,因此也是優化的重中之重,因此,各類策略也考慮的較多,在將資料放入這一級快取之前,需要考慮一些前提條件:

i. 資料不會被第三方修改(比如,是否有另乙個應用也在修改這些資料?)

ii. 資料不會太大

iii. 資料不會頻繁更新(否則使用cache可能適得其反)

iv. 資料會被頻繁查詢

v. 資料不是關鍵資料(如涉及錢,安全等方面的問題)。

快取有幾種形式,可以在對映檔案中配置:read-only(唯讀,適用於很少變更的靜態資料/歷史資料),nonstrict-read-write,read-write(比較普遍的形式,效率一般),transactional(jta中,且支援的快取產品較少)

d) 分布式快取:同c)的配置一樣,只是快取產品的選用不同,在目前的hibernate中可供選擇的不多,oscache, jboss cache,目前的大多數專案,對它們的用於集群的使用(特別是關鍵交易系統)都持保守態度。在集群環境中,只利用資料庫級的快取是最安全的。

5、延遲載入

a) 實體延遲載入:通過使用動態**實現

b) 集合延遲載入:通過實現自有的set/list,hibernate提供了這方面的支援

c) 屬性延遲載入

6、方法選用

a) 完成同樣一件事,hibernate提供了可供選擇的一些方式,但具體使用什麼方式,可能用效能/**都會有影響。顯示,一次返回十萬條記錄(list/set/bag/map等)進行處理,很可能導致記憶體不夠的問題,而如果用基於游標(scrollableresults)或iterator的結果集,則不存在這樣的問題。

b) session的load/get方法,前者會使用二級快取,而後者則不使用。

c) query和list/iterator,如果去仔細研究一下它們,你可能會發現很多有意思的情況,二者主要區別(如果使用了spring,在hibernatetemplate中對應find,iterator方法):

i. list只能利用查詢快取(但在交易系統中查詢快取作用不大),無法利用二級快取中的單個實體,但list查出的物件會寫入二級快取,但它一般只生成較少的執行sql語句,很多情況就是一條(無關聯)。

ii. iterator則可以利用二級快取,對於一條查詢語句,它會先從資料庫中找出所有符合條件的記錄的id,再通過id去快取找,對於快取中沒有的記錄,再構造語句從資料庫中查出,因此很容易知道,如果快取中沒有任何符合條件的記錄,使用iterator會產生n+1條sql語句(n為符合條件的記錄數)

iii. 通過iterator,配合快取管理api,在海量資料查詢中可以很好的解決記憶體問題,如:

while(it.hasnext())

如果用list方法,很可能就出outofmemory錯誤了。

iv. 通過上面的說明,我想你應該知道如何去使用這兩個方法了。

7、集合的選用

在hibernate 3.1文件的「19.5. understanding collection performance」中有詳細的說明。

8、事務控制

事務方面對效能有影響的主要包括:事務方式的選用,事務隔離級別以及鎖的選用。

a) 事務方式選用:如果不涉及多個事務管理器事務的話,不需要使用jta,只有jdbc的事務控制就可以。

b) 事務隔離級別:參見標準的sql事務隔離級別。

c) 鎖的選用:悲觀鎖(一般由具體的事務管理器實現),對於長事務效率低,但安全。樂觀鎖(一般在應用級別實現),如在hibernate中可以定義version欄位,顯然,如果有多個應用運算元據,且這些應用不是用同一種樂觀鎖機制,則樂觀鎖會失效。因此,針對不同的資料應有不同的策略,同前面許多情況一樣,很多時候我們是在效率與安全/準確性上找乙個平衡點,無論如何,優化都不是乙個純技術的問題,你應該對你的應用和業務特徵有足夠的了解。

9、批量操作

即使是使用jdbc,在進行大批資料更新時,batch與不使用batch有效率上也有很大的差別。我們可以通過設定batch_size來讓其支援批量操作。

舉個例子,要批量刪除某錶中的物件,如「delete account」,打出來的語句,會發現hibernate找出了所有account的id,再進行刪除,這主要是為了維護二級快取,這樣效率肯定高不了,在後續的版本中增加了bulk delete/update,但這也無法解決快取的維護問題。也就是說,由於有了二級快取的維護問題,hibernate的批量操作效率並不盡如人意!

從前面許多要點可以看出,很多時候我們是在效率與安全/準確性上找乙個平衡點,無論如何,優化都不是乙個純技術的問題,你應該對你的應用和業務特徵有足夠的了解,一般的,優化方案應在架構設計期就基本確定,否則可能導致沒必要的返工,致使專案延期,而作為架構師和專案經理,還要面對開發人員可能的抱怨,必竟,我們對使用者需求更改的控制力不大,但技術/架構風險是應該在初期意識到並制定好相關的對策。

還有一點要注意,應用層的快取只是錦上添花,永遠不要把它當救命稻草,應用的根基(資料庫設計,演算法,高效的操作語句,恰當api的選擇等)才是最重要的。

Hibernate程式效能優化

初用hibernate的人也許都遇到過效能問題,實現同一功能,用hibernate與用jdbc效能相差十幾倍很正常,如果不及早調整,很可能影響整個專案的進度。大體上,對於hibernate效能調優的主要考慮點如下 資料庫設計調整 hql優化 api的正確使用 如根據不同的業務型別選用不同的集合及查詢...

Hibernate程式效能優化的考慮要點

初用hibernate的人也許都遇到過效能問題,實現同一功能,用hibernate與用jdbc效能相差十幾倍很正常,如果不及早調整,很可能影響整個專案的進度。大體上,對於hibernate效能調優的主要考慮點如下 1 資料庫設計 a 降低關聯的複雜性 b 盡量不使用聯合主鍵 c id的生成機制,不同...

Hibernate程式效能優化的考慮要點

初用hibernate的人也許都遇到過效能問題,實現同一功能,用hibernate與用jdbc效能相差十幾倍很正常,如果不及早調整,很可能影響整個專案的進度。大體上,對於hibernate效能調優的主要考慮點如下 1 資料庫設計 a 降低關聯的複雜性 b 盡量不使用聯合主鍵 c id的生成機制,不同...