導航:首頁 > 網路數據 > hibernate大數據優化

hibernate大數據優化

發布時間:2022-12-22 05:16:44

1. 如何提高hibernate性能

這就意味著 業務層應該載入所有表現層/web層所需的數據,並將這些已實例化完畢的數據返回。通常,應用程序應該 為web層所需的每個集合調用Hibernate.initialize() (這個調用必須發生咱session關閉之前); 或者使用帶有FETCH 從句,或FetchMode.JOIN 的Hibernate查詢, 事先取得所有的數據集合。如果你在應用中使用了Command模式,代替Session Facade , 那麼這項任務將會變得簡單的多。 你也可以通過merge() 或lock() 方法,在訪問未實例化的集合(或代理)之前, 為先前載入的對象綁定一個新的Session 。 顯然,Hibernate將不會,也不應該自動完成這些任務,因為這將引入一個特殊的事務語義。 有時候,你並不需要完全實例化整個大的集合,僅需要了解它的部分信息(例如其大小)、或者集合的部分內容。 你可以使用集合過濾器得到其集合的大小,而不必實例化整個集合: ( (Integer) s.createFilter( collection, "select count(*)" ).list().get(0) ).intValue()這里的createFilter() 方法也可以被用來有效的抓取集合的部分內容,而無需實例化整個集合: s.createFilter( lazyCollection, "").setFirstResult(0).setMaxResults(10).list();20.1.5. 使用批量抓取(Using batch fetching) Hibernate可以充分有效的使用批量抓取,也就是說,如果僅一個訪問代理(或集合),那麼Hibernate將不載入其他未實例化的代理。 批量抓取是延遲查詢抓取的優化方案,你可以在兩種批量抓取方案之間進行選擇:在類級別和集合級別。 類/實體級別的批量抓取很容易理解。假設你在運行時將需要面對下面的問題:你在一個Session 中載入了25個 Cat 實例,每個Cat 實例都擁有一個引用成員owner , 其指向Person ,而Person 類是代理,同時lazy="true" 。 如果你必須遍歷整個cats集合,對每個元素調用getOwner() 方法,Hibernate將會默認的執行25次SELECT 查詢, 得到其owner的代理對象。這時,你可以通過在映射文件的Person 屬性,顯式聲明batch-size ,改變其行為: ...隨之,Hibernate將只需要執行三次查詢,分別為10、10、 5。 你也可以在集合級別定義批量抓取。例如,如果每個Person 都擁有一個延遲載入的Cats 集合, 現在,Sesssion 中載入了10個person對象,遍歷person集合將會引起10次SELECT 查詢, 每次查詢都會調用getCats() 方法。如果你在Person 的映射定義部分,允許對cats 批量抓取, 那麼,Hibernate將可以預先抓取整個集合。請看例子: ... 如果整個的batch-size 是3(筆誤?),那麼Hibernate將會分四次執行SELECT 查詢, 按照3、3、3、1的大小分別載入數據。這里的每次載入的數據量還具體依賴於當前Session 中未實例化集合的個數。 如果你的模型中有嵌套的樹狀結構,例如典型的帳單-原料結構(bill-of-materials pattern),集合的批量抓取是非常有用的。(盡管在更多情況下對樹進行讀取時,嵌套集合(nested set)或原料路徑(materialized path)(××)是更好的解決方法。) 20.1.6. 使用子查詢抓取(Using subselect fetching) 假若一個延遲集合或單值代理需要抓取,Hibernate會使用一個subselect重新運行原來的查詢,一次性讀入所有的實例。這和批量抓取的實現方法是一樣的,不會有破碎的載入。 20.1.7. 使用延遲屬性抓取(Using lazy property fetching) Hibernate3 對單獨的屬性支持延遲抓取,這項優化技術也被稱為組抓取(fetch groups)。請注意,該技術更多的屬於市場特性。在實際應用中,優化行讀取比優化列讀取更重要。但是,僅載入類的部分屬性在某些特定情況下會有用,例如在原有表中擁有幾百列數據、數據模型無法改動的情況下。 可以在映射文件中對特定的屬性設置lazy ,定義該屬性為延遲載入。 屬性的延遲載入要求在其代碼構建時加入二進制指示指令(bytecode instrumentation),如果你的持久類代碼中未含有這些指令, Hibernate將會忽略這些屬性的延遲設置,仍然將其直接載入。 你可以在Ant的Task中,進行如下定義,對持久類代碼加入「二進制指令。」 還有一種可以優化的方法,它使用HQL或條件查詢的投影(projection)特性,可以避免讀取非必要的列, 這一點至少對只讀事務是非常有用的。它無需在代碼構建時「二進制指令」處理,因此是一個更加值得選擇的解決方法。 有時你需要在HQL中通過抓取所有屬性 ,強行抓取所有內容。 20.2. 二級緩存(The Second Level Cache) Hibernate的Session 在事務級別進行持久化數據的緩存操作。 當然,也有可能分別為每個類(或集合),配置集群、或JVM級別(SessionFactory級別 )的緩存。 你甚至可以為之插入一個集群的緩存。注意,緩存永遠不知道其他應用程序對持久化倉庫(資料庫)可能進行的修改 (即使可以將緩存數據設定為定期失效)。 默認情況下,Hibernate使用EHCache進行JVM級別的緩存(目前,Hibernate已經廢棄了對JCS的支持,未來版本中將會去掉它)。 你可以通過設置Hibernate.cache.provider_class 屬性,指定其他的緩存策略, 該緩存策略必須實現org.hibernate.cache.CacheProvider 介面。 表20.1. 緩存策略提供商(Cache Providers) CacheProvider classTypeCluster SafeQuery Cache SupportedHashtable (not intended for proction use)org.hibernate.cache.HashtableCacheProvider memory yesEHCacheorg.hibernate.cache.EhCacheProvider memory, disk yesOSCacheorg.hibernate.cache.OSCacheProvider memory, disk yesSwarmCacheorg.hibernate.cache.SwarmCacheProvider clustered (ip multicast)yes (clustered invalidation) JBoss TreeCacheorg.hibernate.cache.TreeCacheProvider clustered (ip multicast), transactionalyes (replication)yes (clock sync req.) 20.2.1. 緩存映射(Cache mappings) 類或者集合映射的「 元素」可以有下列形式: (1) usage 說明了緩存的策略: transactional 、 read-write 、 nonstrict-read-write 或 read-only 。 另外(首選?), 你可以在hibernate.cfg.xml中指定 和 元素。 這里的usage 屬性指明了緩存並發策略(cache concurrency strategy)。 20.2.2. 策略:只讀緩存(Strategy: read only) 如果你的應用程序只需讀取一個持久化類的實例,而無需對其修改, 那麼就可以對其進行只讀 緩存。這是最簡單,也是實用性最好的方法。甚至在集群中,它也能完美地運作。 ....20.2.3. 策略:讀/寫緩存(Strategy: read/write) 如果應用程序需要更新數據,那麼使用讀/寫緩存 比較合適。 如果應用程序要求「序列化事務」的隔離級別(serializable transaction isolation level),那麼就決不能使用這種緩存策略。 如果在JTA環境中使用緩存,你必須指定Hibernate.transaction.manager_lookup_class 屬性的值, 通過它,Hibernate才能知道該應用程序中JTA的TransactionManager 的具體策略。 在其它環境中,你必須保證在Session.close() 、或Session.disconnect() 調用前, 整個事務已經結束。 如果你想在集群環境中使用此策略,你必須保證底層的緩存實現支持鎖定(locking)。Hibernate內置的緩存策略並不支持鎖定功能。 .... .... 20.2.4. 策略:非嚴格讀/寫緩存(Strategy: nonstrict read/write) 如果應用程序只偶爾需要更新數據(也就是說,兩個事務同時更新同一記錄的情況很不常見),也不需要十分嚴格的事務隔離, 那麼比較適合使用非嚴格讀/寫緩存 策略。如果在JTA環境中使用該策略, 你必須為其指定Hibernate.transaction.manager_lookup_class 屬性的值, 在其它環境中,你必須保證在Session.close() 、或Session.disconnect() 調用前, 整個事務已經結束。 20.2.5. 策略:事務緩存(transactional) Hibernate的事務緩存 策略提供了全事務的緩存支持, 例如對JBoss TreeCache的支持。這樣的緩存只能用於JTA環境中,你必須指定 為其Hibernate.transaction.manager_lookup_class 屬性。 沒有一種緩存提供商能夠支持上列的所有緩存並發策略。下表中列出了各種提供器、及其各自適用的並發策略。 表20.2. 各種緩存提供商對緩存並發策略的支持情況(Cache Concurrency Strategy Support) Cacheread-onlynonstrict-read-writeread-writetransactionalHashtable (not intended for proction use)yesyesyes EHCacheyesyesyes OSCacheyesyesyes SwarmCacheyesyes JBoss TreeCacheyes yes 20.3. 管理緩存(Managing the caches) 無論何時,當你給save() 、update() 或 saveOrUpdate() 方法傳遞一個對象時,或使用load() 、 get() 、list() 、iterate() 或scroll() 方法獲得一個對象時, 該對象都將被加入到Session 的內部緩存中。 當隨後flush()方法被調用時,對象的狀態會和資料庫取得同步。 如果你不希望此同步操作發生,或者你正處理大量對象、需要對有效管理內存時,你可以調用evict() 方法,從一級緩存中去掉這些對象及其集合。 ScrollableResult cats = sess.createQuery("from Cat as cat").scroll(); //a huge result setwhile ( cats.next() ) { Cat cat = (Cat) cats.get(0); doSomethingWithACat(cat); sess.evict(cat);}Session還提供了一個contains() 方法,用來判斷某個實例是否處於當前session的緩存中。 如若要把所有的對象從session緩存中徹底清除,則需要調用Session.clear() 。 對於二級緩存來說,在SessionFactory 中定義了許多方法, 清除緩存中實例、整個類、集合實例或者整個集合。 sessionFactory.evict(Cat.class, catId); //evict a particular CatsessionFactory.evict(Cat.class); //evict all CatssessionFactory.evictCollection("Cat.kittens", catId); //evict a particular collection of kittenssessionFactory.evictCollection("Cat.kittens"); //evict all kitten collectionsCacheMode 參數用於控制具體的Session如何與二級緩存進行交互。 CacheMode.NORMAL - 從二級緩存中讀、寫數據。 CacheMode.GET - 從二級緩存中讀取數據,僅在數據更新時對二級緩存寫數據。 CacheMode.PUT - 僅向二級緩存寫數據,但不從二級緩存中讀數據。 CacheMode.REFRESH - 僅向二級緩存寫數據,但不從二級緩存中讀數據。通過 Hibernate.cache.use_minimal_puts 的設置,強制二級緩存從資料庫中讀取數據,刷新緩存內容。 如若需要查看二級緩存或查詢緩存區域的內容,你可以使用統計(Statistics) API。 Map cacheEntries = sessionFactory.getStatistics() .getSecondLevelCacheStatistics(regionName) .getEntries();此時,你必須手工打開統計選項。可選的,你可以讓Hibernate更人工可讀的方式維護緩存內容。 Hibernate.generate_statistics truehibernate.cache.use_structured_entries true20.4. 查詢緩存(The Query Cache) 查詢的結果集也可以被緩存。只有當經常使用同樣的參數進行查詢時,這才會有些用處。 要使用查詢緩存,首先你必須打開它: Hibernate.cache.use_query_cache true該設置將會創建兩個緩存區域 - 一個用於保存查詢結果集(org.hibernate.cache.StandardQueryCache ); 另一個則用於保存最近查詢的一系列表的時間戳(org.hibernate.cache.UpdateTimestampsCache )。 請注意:在查詢緩存中,它並不緩存結果集中所包含的實體的確切狀態;它只緩存這些實體的標識符屬性的值、以及各值類型的結果。 所以查詢緩存通常會和二級緩存一起使用。 絕大多數的查詢並不能從查詢緩存中受益,所以Hibernate默認是不進行查詢緩存的。如若需要進行緩存,請調用 Query.setCacheable(true) 方法。這個調用會讓查詢在執行過程中時先從緩存中查找結果, 並將自己的結果集放到緩存中去。 如果你要對查詢緩存的失效政策進行精確的控制,你必須調用Query.setCacheRegion() 方法, 為每個查詢指定其命名的緩存區域。 List blogs = sess.createQuery("from Blog blog where blog.blogger = :blogger") .setEntity("blogger", blogger) .setMaxResults(15) .setCacheable(true) .setCacheRegion("frontpages") .list();如果查詢需要強行刷新其查詢緩存區域,那麼你應該調用Query.setCacheMode(CacheMode.REFRESH) 方法。 這對在其他進程中修改底層數據(例如,不通過Hibernate修改數據),或對那些需要選擇性更新特定查詢結果集的情況特別有用。 這是對SessionFactory.evictQueries() 的更為有效的替代方案,同樣可以清除查詢緩存區域。 20.5. 理解集合性能(Understanding Collection performance) 前面我們已經對集合進行了足夠的討論。本段中,我們將著重講述集合在運行時的事宜。 20.5.1. 分類(Taxonomy) Hibernate定義了三種基本類型的集合: 值數據集合 一對多關聯 多對多關聯 這個分類是區分了不同的表和外鍵關系類型,但是它沒有告訴我們關系模型的所有內容。 要完全理解他們的關系結構和性能特點,我們必須同時考慮「用於Hibernate更新或刪除集合行數據的主鍵的結構」。 因此得到了如下的分類: 有序集合類 集合(sets) 包(bags) 所有的有序集合類(maps, lists, arrays)都擁有一個由 和 組成的主鍵。 這種情況下集合類的更新是非常高效的――主鍵已經被有效的索引,因此當Hibernate試圖更新或刪除一行時,可以迅速找到該行數據。 集合(sets)的主鍵由 和其他元素欄位構成。 對於有些元素類型來說,這很低效,特別是組合元素或者大文本、大二進制欄位; 資料庫可能無法有效的對復雜的主鍵進行索引。 另一方面,對於一對多、多對多關聯,特別是合成的標識符來說,集合也可以達到同樣的高效性能。( 附註:如果你希望SchemaExport 為你的 創建主鍵, 你必須把所有的欄位都聲明為not-null="true" 。) 映射定義了代理鍵,因此它總是可以很高效的被更新。事實上, 擁有著最好的性能表現。 Bag是最差的。因為bag允許重復的元素值,也沒有索引欄位,因此不可能定義主鍵。 Hibernate無法判斷出重復的行。當這種集合被更改時,Hibernate將會先完整地移除 (通過一個(in a single DELETE ))整個集合,然後再重新創建整個集合。 因此Bag是非常低效的。 請注意:對於一對多關聯來說,「主鍵」很可能並不是資料庫表的物理主鍵。 但就算在此情況下,上面的分類仍然是有用的。(它仍然反映了Hibernate在集合的各數據行中是如何進行「定位」的。) 20.5.2. Lists, maps 和sets用於更新效率最高 根據我們上面的討論,顯然有序集合類型和大多數set都可以在增加、刪除、修改元素中擁有最好的性能。 可論證的是對於多對多關聯、值數據集合而言,有序集合類比集合(set)有一個好處。因為Set 的內在結構, 如果「改變」了一個元素,Hibernate並不會更新(UPDATE) 這一行。 對於Set 來說,只有在插入(INSERT) 和刪除(DELETE) 操作時「改變」才有效。再次強調:這段討論對「一對多關聯」並不適用。 注意到數組無法延遲載入,我們可以得出結論,list, map和idbags是最高效的(非反向)集合類型,set則緊隨其後。 在Hibernate中,set應該時最通用的集合類型,這時因為「set」的語義在關系模型中是最自然的。 但是,在設計良好的Hibernate領域模型中,我們通常可以看到更多的集合事實上是帶有inverse="true" 的一對多的關聯。對於這些關聯,更新操作將會在多對一的這一端進行處理。因此對於此類情況,無需考慮其集合的更新性能。 20.5.3. Bag和list是反向集合類中效率最高的 在把bag扔進水溝之前,你必須了解,在一種情況下,bag的性能(包括list)要比set高得多: 對於指明了inverse="true" 的集合類(比如說,標準的雙向的一對多關聯), 我們可以在未初始化(fetch)包元素的情況下直接向bag或list添加新元素! 這是因為Collection.add() )或者Collection.addAll() 方法 對bag或者List總是返回true(這點與與Set不同)。因此對於下面的相同代碼來說,速度會快得多。 Parent p = (Parent) sess.load(Parent.class, id); Child c = new Child(); c.setParent(p); p.getChildren().add(c); //no need to fetch the collection! sess.flush();20.5.4. 一次性刪除(One shot delete) 偶爾的,逐個刪除集合類中的元素是相當低效的。Hibernate並沒那麼笨, 如果你想要把整個集合都刪除(比如說調用list.clear()),Hibernate只需要一個DELETE就搞定了。 假設我們在一個長度為20的集合類中新增加了一個元素,然後再刪除兩個。 Hibernate會安排一條INSERT 語句和兩條DELETE 語句(除非集合類是一個bag)。 這當然是顯而易見的。 但是,假設我們刪除了18個數據,只剩下2個,然後新增3個。則有兩種處理方式: 逐一的刪除這18個數據,再新增三個; 刪除整個集合類(只用一句DELETE語句),然後增加5個數據。 Hibernate還沒那麼聰明,知道第二種選擇可能會比較快。 (也許讓Hibernate不這么聰明也是好事,否則可能會引發意外的「資料庫觸發器」之類的問題。) 幸運的是,你可以強制使用第二種策略。你需要取消原來的整個集合類(解除其引用), 然後再返回一個新的實例化的集合類,只包含需要的元素。有些時候這是非常有用的。 顯然,一次性刪除並不適用於被映射為inverse="true" 的集合。 20.6. 監測性能(Monitoring performance) 沒有監測和性能參數而進行優化是毫無意義的。Hibernate為其內部操作提供了一系列的示意圖,因此可以從 每個SessionFactory 抓取其統計數據。 20.6.1. 監測SessionFactory 你可以有兩種方式訪問SessionFactory 的數據記錄,第一種就是自己直接調用 sessionFactory.getStatistics() 方法讀取、顯示統計 數據。 此外,如果你打開StatisticsService MBean選項,那麼Hibernate則可以使用JMX技術 發布其數據記錄。你可以讓應用中所有的SessionFactory 同時共享一個MBean,也可以每個 SessionFactory分配一個MBean。下面的代碼即是其演示代碼: // MBean service registration for a specific SessionFactoryHashtable tb = new Hashtable();tb.put("type", "statistics");tb.put("sessionFactory", "myFinancialApp");ObjectName on = new ObjectName("hibernate", tb); // MBean object nameStatisticsService stats = new StatisticsService(); // MBean implementationstats.setSessionFactory(sessionFactory); // Bind the stats to a SessionFactoryserver.registerMBean(stats, on); // Register the Mbean on the server// MBean service registration for all SessionFactory'sHashtable tb = new Hashtable();tb.put("type", "statistics");tb.put("sessionFactory", "all");ObjectName on = new ObjectName("hibernate", tb); // MBean object nameStatisticsService stats = new StatisticsService(); // MBean implementationserver.registerMBean(stats, on); // Register the MBean on the serverTODO:仍需要說明的是:在第一個例子中,我們直接得到和使用MBean;而在第二個例子中,在使用MBean之前 我們則需要給出SessionFactory的JNDI名,使用hibernateStatsBean.setSessionFactoryJNDIName("my/JNDI/Name") 得到SessionFactory,然後將MBean保存於其中。 你可以通過以下方法打開或關閉SessionFactory 的監測功能: 在配置期間,將Hibernate.generate_statistics 設置為true 或false ; 在運行期間,則可以可以通過sf.getStatistics().setStatisticsEnabled(true) 或hibernateStatsBean.setStatisticsEnabled(true) 你也可以在程序中調用clear() 方法重置統計數據,調用logSummary() 在日誌中記錄(info級別)其總結。 20.6.2. 數據記錄(Metrics) Hibernate提供了一系列數據記錄,其記錄的內容包括從最基本的信息到與具體場景的特殊信息。所有的測量值都可以由 Statistics 介面進行訪問,主要分為三類: 使用Session 的普通數據記錄,例如打開的Session的個數、取得的JDBC的連接數等; 實體、集合、查詢、緩存等內容的統一數據記錄 和具體實體、集合、查詢、緩存相關的詳細數據記錄 例如:你可以檢查緩存的命中成功次數,緩存的命中失敗次數,實體、集合和查詢的使用概率,查詢的平均時間等。請注意 java中時間的近似精度是毫秒。

2. hibernate 查詢語句好優化嗎

hibernate對單表的控制能力比較優秀,但是對於比較復雜的再加上分頁的動態查詢,僅僅是查詢,沒有問題。hibernate的分頁也已經針對不同的資料庫進行了優化的
比如oracle,hibernate就採用的是oracle最快的分頁方式,具體的可以去看OracleDialect源代碼
其他的資料庫也是

對於特別龐大的數據,hibernate的get和load方法也是不管有多少全查的,對大數據,get或者load是獲取一條數據,這里都需要用延遲載入的
批量sql的時候,需要設置batch size,並且關閉二級緩存,同時使用flush來同步資料庫,在使用clear來清空session緩存,這樣不至於內存溢出,hibernte文檔上有這個例子
或者用存儲過程,如果你了解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語句來抓取當前對象的關聯實體和集合
在我的開發經歷中,此處對性能的優化是比較有限的,並不值得過多關注
2)何時抓取
主要分為延遲載入和立即抓取,默認的情況下Hibernate3對對象關聯實採用延遲載入,普通屬性採用立即抓取,通過延遲載入和採用適當的抓取粒度,與不採用優化相比往往可以將性能提升數倍
立即抓取:當抓取宿主對象時,同時抓取其關聯對象和關聯集以及屬性
延遲載入:當抓取宿主對象時,並不抓取其關聯對象,而是當對其對象進行調用時才載入
對於延遲載入,需要注意的時,對延遲對象的使用必須在Session關閉之前進行,Hibernate的
LazyInitalizationException往往就是由於在Session的生命期外使用了延遲載入的對象。當我們進行Web開發時,可以使用 OpenSessionInView模式,當請求開始時打開session,當請求響應結束時才關閉session,不過,在使用 OpenSessionInView模式時,需要注意如果響應時間比較長(業務比較復雜或者客戶端是低速網路),將Session資源(也就是資料庫的連 接)佔用太久的話可以會導致資源耗盡
3)抓取粒度
抓取粒度指的是對象在關聯關系之間被導航時一次預先載入的數量,Hibernate程序的性能比較差往往就在於沒有對抓取粒度仔細考慮,當載入一個列表並在列表中的每個對象中對其關聯進行導航時,往往導致N+1條SQL語句查詢。
對該值並沒有一個約定俗成的值,根據情況而定,如果被關聯表數據比較少,則可以設置地小一
些,3-20,如果比較大則可以設到30-50,注意的時候,並不是越多越好,當其值超過50之後,對性能並沒有多大改善但卻無謂地消耗內存
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>
該設置對性能的提升比較有限

3. 如何優化hibernate

是設定JDBC的Statement讀取數據的時候每次從資料庫中取出的記錄條數,一般設置為30、50、100。Oracle資料庫的JDBC驅動默認的Fetch
Size=15,設置Fetch
Size設置為:30、50,性能會有明顯提升,如果繼續增大,超出100,性能提升不明顯,反而會消耗內存。
即在hibernate配製文件中進行配製:
1 <property name="hibernateProperties">
2 <props>3 <propkey="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
4 <prop key="hibernate.show_sql">false</prop>
5 <!-- Create/update the database tables automatically when the JVMstarts up
6 <prop key="hibernate.hbm2ddl.auto">update</prop> -->
7 <!-- Turn batching off for better error messages underPostgreSQL
8 <prop key="hibernate.jdbc.batch_size">100</prop> -->
9 <prop key="hibernate.jdbc.batch_size">50</prop>
10 </props>
11 </property>Fetch Size設的越大,讀資料庫的次數越少,速度越快;Fetch
Size越小,讀資料庫的次數越多,速度越慢。
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條以內。越少越好。
以上是在進行struts+hibernate+spring進行項目開發中,對hibernate性能優化的幾點心得。

4. 如何優化hibernate

① 制定合理的緩存策略(二級緩存、查詢緩存)。
② 採用合理的Session管理機制。
③ 盡量使用延遲載入特性。
④ 設定合理的批處理參數。
⑤ 如果可以,選用UUID作為主鍵生成器。
⑥ 如果可以,選用基於版本號的樂觀鎖替代悲觀鎖。
⑦ 在開發過程中, 開啟hibernate.show_sql選項查看生成的SQL,從而了解底層的狀況;開發完成後關閉此選項。
⑧ 考慮資料庫本身的優化,合理的索引、恰當的數據分區策略等都會對持久層的性能帶來可觀的提升,但這些需要專業的DBA(資料庫管理員)提供支持。
Hibernate的悲觀鎖和樂觀鎖機制。
有些業務邏輯在執行過程中要求對數據進行排他性的訪問,於是需要通過一些機制保證在此過程中數據被鎖住不會被外界修改,這就是所謂的鎖機制。
Hibernate支持悲觀鎖和樂觀鎖兩種鎖機制。悲觀鎖,顧名思義悲觀的認為在數據處理過程中極有可能存在修改數據的並發事務(包括本系統的其他事務或來自外部系統的事務),於是將處理的數據設置為鎖定狀態。悲觀鎖必須依賴資料庫本身的鎖機制才能真正保證數據訪問的排他性,關於資料庫的鎖機制和事務隔離級別在《Java面試題大全(上)》中已經討論過了。樂觀鎖,顧名思義,對並發事務持樂觀態度(認為對數據的並發操作不會經常性的發生),通過更加寬松的鎖機制來解決由於悲觀鎖排他性的數據訪問對系統性能造成的嚴重影響。最常見的樂觀鎖是通過數據版本標識來實現的,讀取數據時獲得數據的版本號,更新數據時將此版本號加1,然後和資料庫表對應記錄的當前版本號進行比較,如果提交的數據版本號大於資料庫中此記錄的當前版本號則更新數據,否則認為是過期數據無法更新。Hibernate中通過Session的get()和load()方法從資料庫中載入對象時可以通過參數指定使用悲觀鎖;而樂觀鎖可以通過給實體類加整型的版本欄位再通過XML或@Version註解進行配置。
提示:使用樂觀鎖會增加了一個版本欄位,很明顯這需要額外的空間來存儲這個版本欄位,浪費了空間,但是樂觀鎖會讓系統具有更好的並發性,這是對時間的節省。因此樂觀鎖也是典型的空間換時間的策略。
Hibernate的延遲載入機制。
延遲載入就是並不是在讀取的時候就把數據載入進來,而是等到使用時再載入。Hibernate使用了虛擬代理機制實現延遲載入,我們使用Session的load()方法載入數據或者一對多關聯映射在使用延遲載入的情況下從一的一方載入多的一方,得到的都是虛擬代理,簡單的說返回給用戶的並不是實體本身,而是實體對象的代理。代理對象在用戶調用getter方法時才會去資料庫載入數據。但載入數據就需要資料庫連接。而當我們把會話關閉時,資料庫連接就同時關閉了。
延遲載入與session關閉的矛盾一般可以這樣處理:

關閉延遲載入特性。這種方式操作起來比較簡單,因為Hibernate的延遲載入特性是可以通過映射文件或者註解進行配置的,但這種解決方案存在明顯的缺陷。首先,出現"no
session or session was closed"通常說明系統中已經存在主外鍵關聯,如果去掉延遲載入的話,每次查詢的開銷都會變得很大。

在session關閉之前先獲取需要查詢的數據,可以使用工具方法Hibernate.isInitialized()判斷對象是否被載入,如果沒有被載入則可以使用Hibernate.initialize()方法載入對象。

使用攔截器或過濾器延長Session的生命周期直到視圖獲得數據。Spring整合Hibernate提供的OpenSessionInViewFilter和OpenSessionInViewInterceptor就是這種做法。
Hibernate的一級緩存、二級緩存和查詢緩存
Hibernate的Session提供了一級緩存的功能,默認總是有效的,當應用程序保存持久化實體、修改持久化實體時,Session並不會立即把這種改變提交到資料庫,而是緩存在當前的Session中,除非顯示調用了Session的flush()方法或通過close()方法關閉Session。通過一級緩存,可以減少程序與資料庫的交互,從而提高資料庫訪問性能。
SessionFactory級別的二級緩存是全局性的,所有的Session可以共享這個二級緩存。不過二級緩存默認是關閉的,需要顯示開啟並指定需要使用哪種二級緩存實現類(可以使用第三方提供的實現)。一旦開啟了二級緩存並設置了需要使用二級緩存的實體類,SessionFactory就會緩存訪問過的該實體類的每個對象,除非緩存的數據超出了指定的緩存空間。
一級緩存和二級緩存都是對整個實體進行緩存,不會緩存普通屬性,如果希望對普通屬性進行緩存,可以使用查詢緩存。查詢緩存是將HQL或SQL語句以及它們的查詢結果作為鍵值對進行緩存,對於同樣的查詢可以直接從緩存中獲取數據。查詢緩存默認也是關閉的,需要顯示開啟。

5. 介紹一下hibernate的工作原理,優點以及如何優化

hibernate,通過對jdbc進行封裝,對 java類和 關系資料庫進行mapping,實現了對關系資料庫的面向對象方式的操作,改變了傳統的jdbc + sql操作數據的方式,從而使開發人員可以花更多精力進行對象方面的開發
好處呢,並不只是簡化了資料庫操作,更有價值的是對不同的資料庫提供了統一操作的介面,使應用程序的跨資料庫開發成為可能

1.讀取並解析配置文件。
2.讀取並解析映射信息,創建SessionFactory
3.打開Session
4.創建事物Transaction
5.持久化操作
6.提交事務
7.關閉Session
8.關閉SessionFactory

6. hibernate導入大量數據時怎樣處理內存中的數據

hibernate插入大數據
1:把數據量分成幾塊(如1000條為一塊)導入,然後清除緩存(否則容易內存溢出)。

7. hibernate如何避免復雜查詢,優化大數據,和批量sql語句求答案

------解決方案--------------------------------------------------------
Hibernate 是一個優秀的 ORM 框架,但不是高效的。
大數據量的查詢,以及需要使用本地資料庫語言對 SQL 進行逐步調優的應用不適合使用 Hibernate
------解決方案--------------------------------------------------------
僅僅是查詢,沒有問題。hibernate的分頁也已經針對不同的資料庫進行了優化的
比如oracle,hibernate就採用的是oracle最快的分頁方式,具體的可以去看OracleDialect源代碼
其他的資料庫也是
get或者load是獲取一條數據,這里都需要用延遲載入的
批量sql的時候,需要設置batch size,並且關閉二級緩存,同時使用flush來同步資料庫,在使用clear來清空session緩存,這樣不至於內存溢出
,hibernte文檔上有這個例子
或者用存儲過程,如果你了解hibernate你就會用他的長處,而避免其短處
------解決方案--------------------------------------------------------
hibernate的查詢緩存key是查詢語句,但是key對應的value其實是資料庫表的主鍵
當查詢被緩存後,再次調用查詢的時候,通過key找到對應的id集合,然後一個一個的去class緩存中去load
class里沒有,再去資料庫中獲取。所以這又涉及到類緩存上了,當用hibernate進行資料庫的修改和刪除等操作的時候,都會更新一二級緩存,所以查詢緩存會獲取最新的數據
------解決方案--------------------------------------------------------

閱讀全文

與hibernate大數據優化相關的資料

熱點內容
ps入門必備文件 瀏覽:348
以前的相親網站怎麼沒有了 瀏覽:15
蘋果6耳機聽歌有滋滋聲 瀏覽:768
怎麼徹底刪除linux文件 瀏覽:379
編程中字體的顏色是什麼意思 瀏覽:534
網站關鍵詞多少個字元 瀏覽:917
匯川am系列用什麼編程 瀏覽:41
筆記本win10我的電腦在哪裡打開攝像頭 瀏覽:827
醫院單位基本工資去哪個app查詢 瀏覽:18
css源碼應該用什麼文件 瀏覽:915
編程ts是什麼意思呢 瀏覽:509
c盤cad佔用空間的文件 瀏覽:89
不銹鋼大小頭模具如何編程 瀏覽:972
什麼格式的配置文件比較主流 瀏覽:984
增加目錄word 瀏覽:5
提取不相鄰兩列數據如何做圖表 瀏覽:45
r9s支持的網路制式 瀏覽:633
什麼是提交事務的編程 瀏覽:237
win10打字卡住 瀏覽:774
linux普通用戶關機 瀏覽:114

友情鏈接