優化hibernate性能的幾點建議

轉載:http://blog.csdn.net/yuhua3272004/article/details/5193055

1、針對oracle數據庫而言,Fetch Size 是設定JDBC的Statement讀取數據的時候每次從數據庫中取出的記錄條數,一般設置爲30、50、100。Oracle數據庫的JDBC驅動默認的Fetch Size=15,設置Fetch Size設置爲:30、50,性能會有明顯提升,如果繼續增大,超出100,性能提升不明顯,反而會消耗內存。

  即在hibernate配製文件中進行配製:

1 <property name="hibernateProperties">
2 <props>
3 <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
4 <prop key="hibernate.show_sql">false</prop>
5 <!-- Create/update the database tables automatically when the JVM starts up
6 <prop key="hibernate.hbm2ddl.auto">update</prop> -->
7 <!-- Turn batching off for better error messages under PostgreSQL
8 <prop key="hibernate.jdbc.fetch_size">100</prop> -->
9 <prop key="hibernate.jdbc.batch_size">50</prop>
10 </props>
11 </property>Fetch Size設的越大,讀數據庫的次數越少,速度越快;Fetch Size越小,讀數據庫的次數越多,速度越慢。

  hibernate.jdbc.fetch_size 意義解釋:
   非零值,指定JDBC抓取數量的大小 (調用Statement.setFetchSize()).
  1. /**   
  2.  * Gives the JDBC driver a hint as to the number of rows that should   
  3.  * be fetched from the database when more rows are needed.  The number   
  4.  * of rows specified affects only result sets created using this   
  5.  * statement. If the value specified is zero, then the hint is ignored.   
  6.  * The default value is zero.   
  7.  *   
  8.  * @param rows the number of rows to fetch   
  9.  * @exception SQLException if a database access error occurs, or the   
  10.  *        condition 0 <= <code>rows</code> <= <code>this.getMaxRows()</code>   
  11.  *        is not satisfied.   
  12.  * @since 1.2   
  13.  * @see #getFetchSize   
  14.  */  

      hibernate.jdbc.batch_size

    非零值,允許Hibernate使用JDBC2的批量更新. 取值 建議取530之間的值。設定一次最多可以提交多少sql語句的上限,提高sql語句的執行效率 。

數據批量操作時可以通過配置
<session-factory>
    ...
    <property name="hibernate.jdbc.batch_size">50</property>
    ...
</session.factory>
來指定當我們發起SQL調用的時候累計到50個SQL之後批量提交。
同一個SessionFactory創建出來的一個session,一個進行批量操作,執行了100次SQL語句,對數據庫進行了兩次操作。

 

      2、如果是超大的系統,建議生成htm文件。加快頁面提升速度。

  3、不要把所有的責任推在hibernate上,對代碼進行重構,減少對數據庫的操作,儘量避免在數據庫查詢時使用in操作,以及避免遞歸查詢操作,代碼質量、系統設計的合理性決定系統性能的高低。

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

  (1). 使用List()返回結果時,Hibernate會所有查詢結果初始化爲持久化對象,結果集較大時,會佔用很多的處理時間。

  (2). 而使用iterator()返回結果時,在每次調用iterator.next()返回對象並使用對象時,Hibernate才調用查詢將對應的對象初始化,對於大數據量時,每調用一次查詢都會花費較多的時間。當結果集較大,但是含有較大量相同的數據,或者結果集不是全部都會使用時,使用iterator()纔有優勢。

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

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

  7、 對於大數據量新增、修改、刪除操作或者是對大數據量的查詢,與數據庫的交互次數是決定處理時間的最重要因素,減少交互的次數是提升效率的最好途徑,所以在開發過程中,請將show_sql設置爲true,深入瞭解Hibernate的處理過程,嘗試不同的方式,可以使得效率提升。儘可能對每個頁面的顯示,對數據庫的操作減少到100----150條以內。越少越好。
-------------------------------------------------------------

 批量插入

  在項目的開發過程之中,由於項目需求,我們常常需要把大批量的數據插入到數據庫。數量級有萬級、十萬級、百萬級、甚至千萬級別的。如此數量級別的數據用Hibernate做插入操作,就可能會發生異常,常見的異常是OutOfMemoryError(內存溢出異常)。
  基本思路:優化Hibernate,在配置文件中設置hibernate.jdbc.batch_size參數,來指定每次提交SQL的數量;程序上採用分段插入及時清除緩存的方法(Session實現了異步write-behind,它允許Hibernate顯式地寫操作的批處理),也就是每插入一定量的數據後及時的把它們從內部緩存中清除掉,釋放佔用的內存。
設置hibernate.jdbc.batch_size參數,配置如下。
<hibernate-configuration>
<session-factory>
.........
<property name=” hibernate.jdbc.batch_size”>50</property>
.........
<session-factory>
<hibernate-configuration>

配置hibernate.jdbc.batch_size參數的原因就是儘量少讀數據庫,hibernate.jdbc.batch_size參數值越大,讀數據庫的次數越少,速度越快。從上面的配置可以看出,Hibernate是等到程序積累到了50個SQL之後再批量提交。

    hibernate.jdbc.batch_size參數值也可能不是設置得越大越好,從性能角度上講還有待商榷。這要考慮實際情況,酌情設置,一般情形設置30、50就可以滿足需求了。
    插入10000條數據爲例,如下:

Session session=HibernateUtil.currentSession();
Transatcion tx=session.beginTransaction();
for(int i=0;i<100000;i++)
...{
Student s=new Student();
s.setName(“Paul”);
session.save(s);
if(i%50==0) //以每50個數據作爲一個處理單元
...{
session.flush(); //保持與數據庫數據的同步
session.clear(); //清除內部緩存的全部數據,及時釋放出佔用的內存
}
}
tx.commit();
.........

在一定的數據規模下,這種做法可以把系統內存資源維持在一個相對穩定的範圍。

如果啓用了二級緩存,從機制上講Hibernate爲了維護二級緩存,我們在做插入、更新、刪除操作時,Hibernate都會往二級緩存充入相應的數據。性能上就會有很大損失,建議在批處理情況下禁用二級緩存。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章