<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    void

    Hibernate性能優化

    有很多人認為Hibernate天生效率比較低,確實,在普遍情況下,需要將執行轉換為SQL語句的 Hibernate的效率低于直接JDBC存取,然而,在經過比較好的性能優化之后,Hibernate的性能還是讓人相當滿意的,特別是應用二級緩存之 后,甚至可以獲得比較不使用緩存的JDBC更好的性能,下面介紹一些通常的Hibernate的優化策略:
        1.抓取優化
         抓取是指Hibernate如何在關聯關系之間進行導航的時候,Hibernate如何獲取關聯對象的策略,其主要定義了兩個方面:如何抓取和何時抓取
         1)如何抓取。
         Hibernate3主要有兩種種抓取方式,分別應用于對象關聯實例(many-to-one、one-to-one)和對象關聯集合(set、map等),總共是四種變種
         JOIN抓取: 通過在SELECT語句中使用OUTER JOIN來獲得對象的關聯實例或者關聯集合)
         SELECT抓?。?另外發送一條SELECT語句來抓取當前對象的關聯實體和集合
         在我的開發經歷中,此處對性能的優化是比較有限的,并不值得過多關注
         例:
         A.應用于對象關聯實例(默認是false)
         <many-to-one name=".." outer-join="true/false/auto"   .../>
         B.應用于對象關聯集合(默認是auto)
         <set name=".." fetch="join/select" ... >
            ....
         </set>
         2)何時抓取
         主要分為延遲加載和立即抓取,默認的情況下Hibernate3對對象關聯實采用延遲加載,普通屬性采用立即抓取,通過延遲加載和采用適當的抓取粒度,與不采用優化相比往往可以將性能提升數倍
         立即抓?。寒斪ト∷拗鲗ο髸r,同時抓取其關聯對象和關聯集以及屬性
         延遲加載:當抓取宿主對象時,并不抓取其關聯對象,而是當對其對象進行調用時才加載
         例:
         A.應用于對象關聯實例(默認是延遲加載)
         <many-to-one name=".."   lazy="true/false" .../>
         B.應用于對象關聯集合(默認是延遲加載)
         <set name=".." lazy="true/false" ... >
            ....
         </set>
         對于延遲加載,需要注意的時,對延遲對象的使用必須在Session關閉之前進行,Hibernate的 LazyInitalizationException往往就是由于在Session的生命期外使用了延遲加載的對象。當我們進行Web開發時,可以使用 OpenSessionInView模式,當請求開始時打開session,當請求響應結束時才關閉session,不過,在使用 OpenSessionInView模式時,需要注意如果響應時間比較長(業務比較復雜或者客戶端是低速網絡),將Session資源(也就是數據庫的連 接)占用太久的話可以會導致資源耗盡
         3)抓取粒度
         抓取粒度指的是對象在關聯關系之間被導航時一次預先加載的數量,Hibernate程序的性能比較差往往就在于沒有對抓取粒度仔細考慮,當加載一個列表并在列表中的每個對象中對其關聯進行導航時,往往導致N+1條SQL語句查詢。
         例:
         A.應用于對象關聯實例(默認為1),注意,對對象關聯實例的設置是在被關聯的對象之上的,譬如
         class User
         {
             Group g;
         }
         那么抓取粒度應該在Group的配置文件之上,見下
         <class name="Group" table="group" batch-size="..">
             ...
         </class>
         對該值并沒有一個約定俗成的值,根據情況而定,如果被關聯表數據比較少,則可以設置地小一些,3-20,如果比較大則可以設到30-50,注意的時候,并不是越多越好,當其值超過50之后,對性能并沒有多大改善但卻無謂地消耗內存
         假設有如下例子:
            List<User> users = query.list();
         如果有20個User,并對這20個User及其Group進行遍歷,如果不設置batch-size(即batch-size="1"),則在最糟糕的情況
         下,需要1 + 20條SQL語句,如果設置batch-size="10",則最好的情況下只需要1 + 2條SQL語句
         B.應用于對象關聯集合(默認為1)
         <set name=".." batch-size="" ... >
            ....
         </set>
         2.二級緩存
         Hibernate 對數據的緩存包括兩個級:一級緩存,在Session的級別上進行,主要是對象緩存,以其id為鍵保存對象,在Session的生命期間存在;二級緩存, 在SessionFactory的級別上進行,有對象緩存和查詢緩存,查詢緩存以查詢條件為鍵保存查詢結果,在SessionFactory的生命期間存 在。默認地,Hibernate只啟用一級緩存,通過正確地使用二級緩存,往往可以獲得意想不到的性能。
         1)對象緩存:
         當抓取一個對象之后,Hiberate將其以id為鍵緩存起來,當下次碰到抓取id相同的對象時,可以使用如下配置
         方法1:在緩存對象上配置
         <class ...>
            <cache useage="read-only/write/...." regions="group" />
         </class>
         useage 表示使用什么類型的緩存,譬如只讀緩存、讀寫緩存等等(具體參見Hibernate參考指南),值得注意的時,有部分緩存在Hibernate的實現中不 支持讀寫緩存,譬如JBossCache在Hibernate的實現中只是一種只讀緩存,具體緩存實現對緩存類型的支持情況,可以參見 org.hibernate.cache包
         regions表示緩存分塊,大部分的緩存實現往往對緩存進行分塊,該部分是可選的,詳細參見各緩存實現
         方法2:在hibernate.cfg.xml中配置
         <cache class=".." useage=".." regions=".."/>
         我認為第二種更好,可以統一管理
         2)查詢緩存
         查詢時候將查詢結果以查詢條件為鍵保存起來,需要配置如下
         A.在hibernate.cfg.xml中配置(啟用查詢緩存)
         <property name="hibernate.cache.use_query_cache">true</property>   (前面的屬性名可參見常量
    org.hibernate.cfg.Enviroment.USE_QUERY_CACHE)
         B.程序
         query.setCacheable(true);
         query.setCacheRegions(...);
         需要注意的是,查詢緩存與對象緩存要結合更有效,因為查詢緩存僅緩存查詢結果列表的主鍵數據
         一般情況下在開發中,對一些比較穩定而又被頻繁引用的數據,譬如數據字典之類的,將其進行二級緩存,對一些查詢條件和查詢數據變化不頻繁而又常常被使用的 查詢,將其進行二級緩存。由于二級緩存是放在內存中,而且Hibernate的緩存不是弱引用緩存(WeekReference),所以注意不要將大塊的 數據放入其中,否則可能會被內存造成比較大的壓力。
         3.批量數據操作
         當進行大批量數據操作(幾萬甚至幾十幾百萬)時,需要注意兩點,一,批量提交,二,及時清除不需要的一級緩存數據
         1) 所謂的批量提交,就是不要頻繁使用session的flush,每一次進行flush,Hibernate將PO數據于數據庫進行同步,對于海量級數據操 作來說是性能災難(同時提交幾千條數據和提交一條數據flush一次性能差別可能會是幾十倍的差異)。一般將數據操作放在事務中,當事務提交時 Hibernate自動幫你進行flush操作。
         2)及時清除不需要的一級緩存數據:由于Hibernate默認采用一級緩存,而在 session的生命期間,所有數據抓取之后會放入一級緩存中,而當數據規模比較龐大時,抓取到內存中的數據會讓內存壓力非常大,一般分批操作數據,被一 次操作之后將一級緩存清除,譬如
         session.clear(User.class)
         4.雜項
         dynamic-insert,dynamic-update,動態插入和動態更新,指的是讓Hibernate插入數據時僅插入非空數據,當修改數據時只修改變化的數據,譬如對于
         class User
         {
            id
            username
            password
         }
         如果u.id=1, u.username="ayufox",u.password=null,那么如果不設置動態插入,則其sql語句是 insert into users(id, username, password) values (1, 'ayufox', '),如果設置則其 sql語句是insert into users(username) valeus('ayufox')
         在如上的情況下,如果修改 u.password='11',那么如果不設置動態更新,則sql語句為update users set username='ayufox', password='11' where id = 1,如果設置則為update user set password='11' where d = 1
         設置是在class的映射文件中,如下
         <class name="User" table="users" dynamic=insert="true/false" dynamic-update="true/false" ...>
         </class>
      該設置對性能的提升比較有限

    posted on 2008-07-19 12:12 void 閱讀(176) 評論(0)  編輯  收藏 所屬分類: Hibernate

    主站蜘蛛池模板: 亚洲男人的天堂久久精品| 国产午夜亚洲不卡| 亚洲伊人久久大香线蕉啊 | 亚洲午夜无码久久久久软件| 最近2022中文字幕免费视频| 亚洲网站在线观看| 精品一区二区三区无码免费视频 | 在线观看无码的免费网站| 亚洲视频在线观看网站| 久久精品视频免费播放| 亚洲av中文无码乱人伦在线播放 | 亚洲精品天堂在线观看| 99re热免费精品视频观看| 亚洲人成网www| 精品国产污污免费网站aⅴ| 亚洲国产日韩在线人成下载| 国内免费高清在线观看| 久久精品国产亚洲AV电影网| 免费人成激情视频| 免费网站观看WWW在线观看| 911精品国产亚洲日本美国韩国| 永久黄色免费网站| 亚洲日韩一中文字暮| 亚洲AV无码一区二三区| 13小箩利洗澡无码视频网站免费| 久久精品7亚洲午夜a| 黄页免费的网站勿入免费直接进入| 亚洲国产成人精品无码一区二区 | 高清永久免费观看| 亚洲欧洲日产韩国在线| 好爽好紧好大的免费视频国产 | 精品熟女少妇av免费久久| 四虎必出精品亚洲高清| 免费a级毛片无码av| 拍拍拍无挡免费视频网站| 亚洲日韩乱码中文无码蜜桃臀 | 无码中文字幕av免费放| 一级特黄录像视频免费| 久久夜色精品国产噜噜亚洲AV| 好吊妞在线成人免费| 中文字幕视频免费在线观看|