瞭解Hibernate的FlushMode.NEVER模式

1、案件背景:java


image
圖片來自於電影《天生殺人狂》


Hibernate並無爲巨型數據集合提供良好的幫助,這也許是開發者認爲這樣沒有太大必要,反而增長Hibernate框架複雜性的緣故吧。因而「極大數據量==批量處理」、「Hibernate/java不是批處理的最佳場所」的觀念在Hibernate開發中大行其道,有些開發者甚至直接利用Hibernate創建session,獲取其connection進而進行jdbc操做。Jdbc並非古董,但在Hibernate中再次call它,不免有些使人無奈。最近在Hibernate的官方罈子上看到Gavin寫給初級用戶的「understand FlushMode.NEVER」,並參考了一下Stripes項目(本人時常關注的時髦項目)做者Tim的blog。在閱讀兩位你們言論後,和你們share一下。

2、性能殺手何在?數據庫


image
圖片來自於電影《這個殺手不太冷》


        Tim在其Blog寫道:「我目前的DNA重組系統,具備複雜而海量的OLTP數據,對付這些在內存的複雜對象(數千個)的方式是依賴用戶接口(非批量處理)來實現用例驅動。」這句半開玩笑的話,是我想起了那男耕女織的生產力低下的生活,真的讓每一個開發者都使用算盤運算嗎?
session.setFlushMode(FlushMode.NEVER);
        這條語句及其簡單,但解決了大問題。它告知Hibernate session不管什麼時候也不要flush任何的狀態變化到數據庫,除非開發者直接調用session.flush()。聽上去很合乎邏輯,但它爲什麼在一些場景中對性能影響甚深,而在其餘的場景中卻好似輕如鵝毛般?
        在Tim的項目中存在着一個十分典型的case(我也不大瞭解生物,這不能怪我):在實驗中利用PCR Primers對遺傳基因(genes)和DNA中的核苷酸序列(exons),這裏的PCR Primers是在PCR處理過程當中用於檢測DNA片斷的物質,對不起你們,本人對生物學詞彙實在無能爲力。檢測匹配過程大體分爲如下7步:
        1.發現本次實驗中全部exons(個數在5000個以上);
        2.查詢本次實驗全部已經排序的PCR Primers;
        3.查詢本次實驗全部待排序的PCR Primers;
        4.獲得與exons對應的Primers找出那些無需轉換的部分;
        5.在系統中爲無需轉換的區域查詢全部可能的PCR Primers;
        6.測試每一個primer找出最佳exons匹配者(Primer);
        7.保存找出的Primer。
        不用擔憂,步驟細節不大明白也不會影響後面的理解。
        因爲domain model極其海量,在第4步咱們可能在一個session中排序20000-30000個對象。而在五、6步的查詢將帶來0-20個附加對象。有趣之處在於當執行第7步將對象save到數據庫時,沒有一個前面裝載的對象被修改過。整個實驗的目的就是僅僅得到這0-20個對象。
在回顧了Tim的生物學場景以後,讓咱們從新回到FlushMode.NEVER的討論上來吧。你可能認爲既然直到最後一步都沒有修改或是持久化任何東西,那麼改變flush模式將收效甚微。固然這是不正確的未參透實質的理解。實際上,在上面流程的起始設置Never這個flush模式、在流程終點手動flush將節省一半的run time,請注意這裏僅提到了run time而沒有將內存、IO計算在內。

3、這個殺手不太「冷」session


image
圖片來自於電影《黑衣人》


        幸虧,這個殺手不太「冷」!這都歸結於Hibernate的髒檢查(dirty checking)。每次裝載一個對象到內存(不能去evict它)時,session始終跟蹤它的修改。因而每次對數據的查詢,session都將跌代全部的session中的對象並檢查髒數據,將髒數據flush到數據庫。Hibernate這樣作的良苦用心是爲了確保在執行查詢以前全部可能影響查詢的變化都被提交到數據庫。這對零星數據量的應用來說,不足爲言。但面對數千個對象和千餘次的查詢來說,它將使性能的真正殺手。
        瞭解真相後,咱們可使用session.setFlushMode(FlushMode.NEVER)語句將在查詢時不需髒檢查的數據(生物實驗中的Primers)標識髒數據,這樣Hibernate無處不在的代理機制將被「欺騙」,直接將它添加到髒數據列表(列表中的數據不會被flush到數據庫)中,這樣「殺手」就會因無處遁形而自動消失了。

4、打造制勝武器:框架


image
圖片來自於電影《致命武器3》



        在讀完這個簡短的「案件」後,咱們也學到了如何在一個session中讀取、查詢大量數據對象狀況下的制勝武器- FlushMode.NEVER。固然要記住,在此過程當中你不能夠修改這些數據,否則就真的把數據「搞髒」了。
        使用武器祕訣以下:dom

        FlushMode previous = session.getFlushMode();        session.flush(); // who know's what been done till now        session.setFlushMode(FlushMode.NEVER);        // Do some querying        // Do some more querying        // Really load up that session        // Execute a few more queries        // Write back to some tables        session.flush();        session.setFlushMode(previous);
相關文章
相關標籤/搜索