1、關於hibernate緩存的問題
Hibernate緩存分爲二級,第一級存放於session中稱爲一級緩存。第二級是由sessionFactory控制的進程級緩存。是全局共享的緩存。查詢時使用緩存的實現過程爲:首先查詢一級緩存中是否具有需要的數據,如果沒有,查詢二級緩存,如果二級緩存中也沒有,此時再執行查詢數據庫的工作。
hibernate會自行維護二級緩存中的數據,以保證緩存中的數據和數據庫中的真實數據的一致性!也就是說刪除、更新、增加數據的時候,同時更新緩存,也包括二級緩存!
當執行load()、 get()、list()、iterate() 或scroll()方法獲得一個對象時, 該對象都將被加入到Session的內部緩存中。
2、適合於使用二級緩存的情況
1、數據不會被第三方修改;
一般情況下,會被hibernate以外修改的數據最好不要配置二級緩存,以免引起不一致的數據。但是如果此數據因爲性能的原因需要被緩存,同時又有可能被第3方比如SQL修改,也可以爲其配置二級緩存。只是此時需要在sql執行修改後手動調用cache的清除方法。以保證數據的一致性
數據大小在可接收範圍之內;
如果數據表數據量特別巨大,此時不適合於二級緩存。原因是緩存的數據量過大可能會引起內存資源緊張,反而降低性能。
如果數據表數據量特別巨大,但是經常使用的往往只是較新的那部分數據。此時,也可爲其配置二級緩存。但是必須單獨配置其持久化類的緩存策略,比如最大緩存數、緩存過期時間等,將這些參數降低至一個合理的範圍(太高會引起內存資源緊張,太低了緩存的意義不大)。
數據更新頻率低;
對於數據更新頻率過高的數據,頻繁同步緩存中數據的代價可能和 查詢緩存中的數據從中獲得的好處相當,壞處益處相抵消。此時緩存的意義也不大。
非關鍵數據(不是財務數據等)
財務數據等是非常重要的數據,絕對不允許出現或使用無效的數據,所以此時爲了安全起見最好不要使用二級緩存。因爲此時 “正確性”的重要性遠遠大於 “高性能”的重要性。
3、Hibernate幾個方法的比較
List方法:
List方法從不使用二級緩存,但會向二級緩存中持久化查詢結果。也就是List方法每次都會從數據進行查詢,並且如果啓用了二級緩存,則Hibernate同時會將所有查詢結果初始化爲持久化對象,如果結果集較大時,這將會佔用很多的處理時間。
Iterate方法:
在無二級緩存的情況下:iterate()方法具有著名的 “n+1” 次查詢的問題,也就是說在第一次查詢時iterate方法會執行滿足條件的查詢結果數再加一次(n+1)的查詢。如果啓用了二級緩存,iterate()方法的查詢過程將是:首先查詢一級緩存中是否具有需要的數據,如果沒有,查詢二級緩存,如果二級緩存中也沒有,此時再執行查詢數據庫的工作。
以下是測試的幾組數據:
機器環境:P43.06 512MB WINXP SP2 MySql5.0.22
數據庫記錄=取出記錄數 |
無緩存 |
緩存 | |||
List |
Iterate |
List |
iterate | ||
1000 |
1 |
704 |
1156 |
3406 |
391 |
2 |
203 |
750 |
203 |
204 | |
3 |
47 |
782 |
93 |
187 | |
4 |
47 |
578 |
79 |
46 | |
5 |
125 |
562 |
125 |
63 | |
2000 |
1 |
1265 |
2719 |
9438 |
531 |
2 |
203 |
1750 |
250 |
266 | |
3 |
188 |
1718 |
250 |
157 | |
4 |
125 |
1719 |
265 |
235 | |
5 |
187 |
1766 |
235 |
265 | |
4000 |
1 |
1438 |
4328 |
16422 |
875 |
2 |
344 |
3344 |
485 |
453 | |
3 |
312 |
3235 |
328 |
453 | |
4 |
312 |
3172 |
484 |
500 | |
5 |
313 |
3203 |
375 |
438 |
100000記錄集情況下
無緩存情況取單條數據10次list平均:6 ms
無緩存情況取單條數據10次iterate平均:13 ms
有緩存情況取單條數據10次iterate平均:10 ms
100000記錄集情況下
無緩存情況取20條數據10次list平均:20 ms
無緩存情況取20條數據10次iterate平均:78 ms
有緩存情況取20條數據10次iterate平均:20ms
100000記錄集情況下
無緩存情況取60條數據10次list平均:20 ms
無緩存情況取60條數據10次iterate平均:170 ms
有緩存情況取60條數據10次iterate平均:26 ms
4、查詢策略比較:
在不使用二級緩存的情況下慎用或者不用Iterate()方法,因爲它會造成n+1次查詢。
在使用二級緩存的情況下,小的數據量並且很小更新的數據可以考慮使用緩存,並且在啓動時加載到緩存中。這樣在查詢時可以使用Iterate()方法來使用二級緩存。
但是注意:當數據量特別大時(比如流水線數據等)需要針對此持久化對象配置其具體的緩存策略,比如設置其存在於緩存中的最大記錄數、緩存存在的時間等參數,以避免系統將大量的數據同時裝載入內存中引起內存資源的迅速耗盡,反而降低系統的性能!但如果最大記錄數、緩存存在的時間,這將會導致緩存命中率很低,這將值得考慮。
5、load()與get()的區別
如果沒有匹配的數據庫記錄,load()方法可能拋出無法恢復的異常(unrecoverable exception)。如果你不確定是否有匹配的行存在,應該使用get()方法,它會立刻訪問數據庫,如果沒有對應的行,會返回null。