8.Hibernate效能最佳化

來源:互聯網
上載者:User

標籤:數字   ehcache   log   fetch   命中   category   擴充   left join   update   

效能最佳化

  1.注意session.clear() 的運用,尤其在不斷分頁的時候

    a) 在一個大集合中進行遍曆,遍曆msg,取出其中額含有敏感字樣的對象

    b) 另外一種形式的記憶體流失( //面試題:Java有記憶體流失嗎?文法層級沒有,但是可由java引起,例如:串連池不關閉,或io讀取後不關閉)

  2.1+N 問題(典型的面試題)

    舉例:當存在多對一關聯性時,多的一方預設是可以取出一的一方的

      @ManyToOne 中 預設為fetch=FetchType.Eager

      當load多的一方時,也會載入一的哪一方,會造成執行不必要的SQL語句

    解決辦法,以下幾種:

      a) @ManyToOne(fetch=FetchType.LAZY) 

      //當多對一(@ManyToOne)已經設定屬性" fetch=FetchType.LAZY "時 

      //只有當需要時(如:t.getCategory().getName()時)才會去擷取關聯表中資料 可以解決N+1問題

      b) @BatchSize

      //在與查詢表(此例中為Topic類)關聯的表類(此例中為Category類)頭處加@BatchSize(size=5)

      //表示每次可查出5條記錄 從而減少了select語句的個數 

      c) join fetch  

      //修改hql語句為--"  from Topic t left join fetch t.category c 

      d) QBC

      //原理和上面那條是一樣的,使用QBC的 createCriteria(*.class)執行查詢 也可避免N+1問題

  

  3.list 和 iterate 不同之處( //主要為了面試)

    a) list 取出表中所有資料構成對象

    b) iterate 先取ID,等用到的時候再根據ID 來取對象

    c) session 中list 第二次發出,仍回到資料庫查詢

    d)iterate 第二次,會先去找 session 緩衝

 

Hibernate 緩衝機制

前面Hibernate中持久化對象的三種狀態有提到,處於Persistent狀態的對象的標誌是 緩衝中也有這個對象

緩衝中類似於一個一個的索引值對,key 為 id,然後value為這個緩衝的對象

當想要對該對象進行讀寫時,會先去查緩衝,

/*一級緩衝和二級緩衝和查詢快取*/

  一級緩衝:session級的緩衝,每個session擁有自己的session緩衝,不同session的session緩衝不能共用

  二級緩衝:sessionFactory級的緩衝,所有的session都可以去訪問二級緩衝

  查詢快取:相同的SQL語句只執行一次

  當緩衝的對象  1.經常被訪問  2.不會經常改動  3.數量不大  時使用二級緩衝

  開啟二級緩衝(兩步):

    1.在 hibernate.cfg.xml中設定:

1         <property name= "cache.use_second_level_cache">true</property>2         <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

    [email protected] 註解 (由hibernate擴充提供)

     @Cache (usage=CacheConcurrencyStrategy.READ_WRITE)  

    (為某個類開啟二級緩衝,針對該類的對象進行的 讀寫操作,會建立二級緩衝)

    註:使用EhCache 二級緩衝需要匯入 ehcache-1.2.3.jar 及 commons-logging-1.0.4.jar 包   

 註: 

  1.load 預設使用二級緩衝,iterate 預設使用二級緩衝

  2.list 預設往二級緩衝加資料,但是查詢的時候不使用

  意思是:session.createQuery("from Category").list();  會將查出來的資料加到緩衝中,但是不會去緩衝中查詢

  3.可以使用<property name="hibernate.cache.use_query_cache">true</property>來開啟查詢快取,預設為關閉,

  查詢快取來標識某個查詢使用緩衝,當執行同一條SQL語句時,就不會再去資料庫找,也是從緩衝中去找該語句 

  在開啟了查詢快取之後,需要注意,調用query.list()操作之前,必須顯示調用query.setCacheable(true)

  例如:session.createQuery("from Category").setCacheable(true).list();

  註:查詢快取只對query.list()起作用,query.iterate不起作用,也就是query.iterate不使用

  

  4.緩衝演算法(新的緩衝對象要進來,怎麼替換):(面試)

  LRU LFU FIFO

  1.Least Recently Used  最近最少使用的被替換

  2.Least Frequently Used  命中率高低  使用頻率最低的被替換

  3.First In First Out  按順序替換

  在ehcache.xml中配置   memoryStoreEvictionPolicy="LRU"

 

事務並發處理

a) 事務:ACID
  Atomic Consistency Itegrity Durability

b) 事務並發時可能出現的問題:

  1.髒讀  (讀到了另一個事務在處理中還未提交的資料)

  2.不可重複讀取 (在事務A的執行過程中,事務B進行了開啟,對列中的資料進行修改和提交,

  導致事務A在事務B執行前讀取的資料和事務B執行後讀取的資料不一致)

  3.虛讀 (在查詢某一條件的資料時,開始查詢後,別人又加入或刪除某些資料,再讀取時與原來的資料不一樣了,

  和 不可重複讀取 類似,不過不可重複讀取針對的列裡面資料的修改,而幻讀針對的是列整體的增刪)

c) 資料庫事務的隔離等級

  1------read-uncommitted

  2------read-committed

  4------repeatable read 

  8------serializable

  前面的數字為Hibernate的交易隔離等級對應的數字

  為什麼要使用1 2 4 8 而不是 1 2 3 4

  1=0000  2=0010  4=0100  8=1000  位元運算效率高

  

  read-uncommitted(允許讀取未提交的資料) 會出現dirty read, phantom-read, non-repeatable read 問題

  read-commited(讀取已提交的資料 項目中一般都使用這個)不會出現dirty read,

  因為只有另一個事務提交才會讀出來結果,但仍然會出現 non-repeatable read 和 phantom-read

  /*使用read-commited機制可用悲觀鎖 樂觀鎖來解決non-repeatable read 和 phantom-read問題*/

  repeatable read(事務執行中其他事務無法執行修改或插入操作     較安全)

  serializable  解決一切問題(順序執行事務 不並發,實際中很少用)

 

  如何設定Hibernate 的交易隔離等級(使用hibernate.connection.isolation配置 取值1、2、4、8)

    1.hibernate.connection.isolation = 2 (如果不設 預設依賴資料庫本身的層級)

    2.用悲觀鎖解決repeatable read的問題(依賴於資料庫的鎖(select... for update))

    hibernate使用Load進行悲觀鎖加鎖    session.load(Inventory.class, 1, LockMode.UPGRADE);   在產生select語句時,會加上for update 進行使用悲觀鎖

      a)LockMode.None   無鎖的機制,Transaction結束時,切換到此模式

      b)LockMode.read   在査詢的時候hibernate會自動擷取鎖

      c)LockMode.write  insert  update hibernate 會自動擷取鎖

      d)以上3種鎖的模式,是hibernate內部使用的(不需要設)

      e)LockMode.UPGRADE_NOWAIT   是 ORACLE 支援的鎖的方式

 

  3.樂觀鎖(其實不是鎖,是一種衝突檢測機制)

  實體類中增加version屬性 (資料庫也會對應產生該欄位初始值為0),並在其get方法前加入 @Version 註解

  則在操作的過程中每更新一次該行資料則version值 加 1,即可在事務提交前判斷該資料是否被其他事務修改過

  (提交事務時,通過對比記憶體中的version值和資料庫中的version值)

 

  註:樂觀和悲觀的區別:

  1.悲觀鎖比較悲觀,覺得會有並發的情況發生,所以提前加了一把鎖,

  2.樂觀鎖比較樂觀,不著急加鎖,而是先判斷是否出現了並發訪問的情況,如果出現了,再做相應的處理

          

8.Hibernate效能最佳化

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.