天天看點

【HIBERNATE架構開發之九】HIBERNATE 性能優化筆記!(周遊、一級/二級/查詢/緩存、樂觀悲觀鎖等優化算法)

1.   循環分頁或者循環進行部分讀取處理資料的時候,使用 session.clear() ;

2.    對應1+n(n+1)問題使用如下解決方式:

1): 使用createcriteria進行查詢(join fetch)

2):hql -> join fetch

3): 使用@fetch設定lazy

4):在@entity下使用注解@batchsize(size=5)

@batchsize  指定每次 讀 取資料的數量

3. list 與 iterate 進行周遊取出資料庫資料的list();

差別1)list 直接取出對象       iterate先會取出元件,需要使用才會使用

差別2)同一個session中每次執行list()取出資料時都會發送sql語句,但是iterate隻會發出一條,預設會去session緩存去找;

4. 緩存,session級别的緩存稱為一級緩存,每個session都有獨立的一級緩存,例如多個線程同時取同一個對象資料;

解決方案:建立一個共用的總緩存(總緩存)二級緩存,如果找不到然後再到各自的session一級混村中尋找;具體操作如下:首先看緩存政策,

【HIBERNATE架構開發之九】HIBERNATE 性能優化筆記!(周遊、一級/二級/查詢/緩存、樂觀悲觀鎖等優化算法)

type : 其中memory支援緩存記憶體中,disk支援緩存存放硬碟中;

cluster safe :是否支援使用在叢集環境;

query cache supported:是否支援查詢緩存(3級緩存)

假設使用ehcacheprovider二級緩存:

1)修改hibernate.cfg.xml配置檔案:

1

2

<property name="cache.use_second_level_cache">true</property>

    <property name="cache.provider_class">org.hibernate.cache.ehcacheprovider</property>

2) 在/hibernate-distribution-3.3.2.ga/project/etc/ehcache.xml 配置檔案拷貝到項目中;

在ehcache.xml中預設如下設定:

     <diskstore path="java.io.tmpdir"/>

3

4

5

6

7

     <defaultcache

        maxelementsinmemory="10000"

        eternal="false"

        timetoidleseconds="120"

        timetoliveseconds="1200"

        overflowtodisk="true"

        />

maxelementsinmemory:在記憶體中最多緩存的對象數量

eternal: 緩存記憶體對象是否永久儲存不删除

timetoidleseconds:  當timetoidleseconds 周期時間沒有被使用過,自動清除掉;(秒)

timetoliveseconds: 緩存對象的生存時間(秒)後自動清楚;

overflowtodisk:溢出的時候是否放置在硬碟上

diskstore  path:預設臨時存放硬碟緩存的路徑

注意:<cache name=”samplecache1″    /> 可以自定義cache名,不自定義不指定預設是用 <defaulecache   ….. />

3)将類使用二級緩存,直接在@entity下使用注解    @cache  其設定如下:

【HIBERNATE架構開發之九】HIBERNATE 性能優化筆記!(周遊、一級/二級/查詢/緩存、樂觀悲觀鎖等優化算法)

常用的read_only (隻讀), read_write(讀寫)

其中@cache(region=””) 使用自定義ehcache.xml的自定義緩存政策設定 ~

4)加入ehcache的jar包,路徑如下:/hibernate-distribution-3.3.2.ga/lib/optional/ehcache/ehcache.jar

加入 commons-logging.jar包

             1.    放入二級緩存如下規則:

                   a)   經常通路  b) 不經常改動(改動不大) c) 資料不是很大 例如使用者權限;

2.     load 預設使用二級緩存,iterate 預設使用二級緩存

3. list 預設往二級緩存加資料,list查詢的使用不使用緩存

4. 如果要 query 查詢語句使用二級緩存,需要打開查詢緩存(同樣的重複的查詢!)

1) hibernate.cfg.xml配置檔案加入配置:

<property name=”cache.use_query_cache”>true</property>

2) 使用query的setcachable(true) 方法指明使用二級緩存 ;

5.    緩存算法:lru 、 lfu 、 fifo

lru: 最近最少被使用的; (時間)

lfu: 使用率比較少的;(次數)

fifo:按照資料從0開始拿走(堆棧)

設定方法:在ehcache.xml繼續設定一個參數: memorystoreevictionpolicy=”lru”

6. 事務隔離機制(為了避免事務并發出現的問題)

1. read-uncommitted : 能讀取沒有送出的資料; 【會出現髒讀等問題,一般不設定此種】

2. read-committed :  隻有送出後才讀;hibernate建議使用!【能解決髒讀但會出現不可重複讀和幻讀問題(手動解決)】

3. repeatable read :      加鎖;(mysql預設使用 repeatable read )

4. serializable :   序列化,解決任何問題,但是效率最低;

mysql 支援這四種事務隔離機制; 事務隔離級别越高效率越慢~

使用 select @@tx_isolation;  查詢事務隔離機制;

     設定隔離機制: set session tx_isolation=’xxx’;  

hibernate解決并發事務方案:使用hibernate悲觀鎖和樂觀鎖進行設定;

1)事務機制的值為1,2,4,8 (ps. 二進制為0001 ,0010,0100,1000 這樣算法效率高)

1.a)使用悲觀鎖:(依賴于資料庫的鎖 解決 repeatable read問題)

在讀取load資料的時候,加入第三個參數::

session.load(xxx.class, 1,lockmode.xxx);

lockmode的值如下:

【HIBERNATE架構開發之九】HIBERNATE 性能優化筆記!(周遊、一級/二級/查詢/緩存、樂觀悲觀鎖等優化算法)

一般隻設定lockmode.upgrade

原因:

none: 無鎖的機制,transaction結束時切換到此模式;

read :在查詢的時候 hibernate會自動擷取鎖;

write ,insert, update hibernate 會自動擷取鎖;

以上 3種鎖的模式是hibernate内部使用的;

upgrade—nowait ->是oracle資料庫 支援的鎖;

     1.b)使用樂觀鎖:(程式内使用字段version進行加鎖,與資料庫沒有關系)

可以定義一個version屬性,然後在getversion上使用注解 @version

注意:當并發的時候會報錯,那麼找個錯誤交給我們自己來處理;  

       悲觀與樂觀:悲觀一開始就進行加鎖,不論是否有其他事務來同時并發;但是樂觀鎖則不進行直接加鎖,而是等待更新時候進行檢查對比下,如果與去之前version不一緻那麼更新下即可;樂觀鎖效率高;