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

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

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

    posts - 73,  comments - 55,  trackbacks - 0

    1. ???? 關(guān)于 hibernate 緩存的問(wèn)題:

    1.1.1. ????? ??? 基本的緩存原理

    Hibernate 緩存分為二級(jí),第一級(jí)存放于 session 中稱為一級(jí)緩存,默認(rèn)帶有且不能卸載。

    ?

    第二級(jí)是由 sessionFactory 控制的進(jìn)程級(jí)緩存。是全局共享的緩存,凡是會(huì)調(diào)用二級(jí)緩存的查詢方法 都會(huì)從中受益。只有經(jīng)正確的配置后二級(jí)緩存才會(huì)發(fā)揮作用。同時(shí)在進(jìn)行條件查詢時(shí)必須使用相應(yīng)的方法才能從緩存中獲取數(shù)據(jù)。比如 Query.iterate() 方法、 load get 方法等。必須注意的是 session.find 方法永遠(yuǎn)是從數(shù)據(jù)庫(kù)中獲取數(shù)據(jù),不會(huì)從二級(jí)緩存中獲取數(shù)據(jù),即便其中有其所需要的數(shù)據(jù)也是如此。

    ?

    查詢時(shí)使用緩存的實(shí)現(xiàn)過(guò)程為:首先查詢一級(jí)緩存中是否具有需要的數(shù)據(jù),如果沒(méi)有,查詢二級(jí)緩存,如果二級(jí)緩存中也沒(méi)有,此時(shí)再執(zhí)行查詢數(shù)據(jù)庫(kù)的工作。要注意的是:此 3 種方式的查詢速度是依次降低的。

    1.2.?? 存在的問(wèn)題

    1.2.1. ????? 一級(jí)緩存的問(wèn)題以及使用二級(jí)緩存的原因

    ??? ? 因?yàn)?/span> Session 的生命期往往很短,存在于 Session 內(nèi)部的第一級(jí)最快緩存的生命期當(dāng)然也很短,所以第一級(jí)緩存的命中率是很低的。其對(duì)系統(tǒng)性能的改善也是很有限的。當(dāng)然,這個(gè) Session 內(nèi)部緩存的主要作用是保持 Session 內(nèi)部數(shù)據(jù)狀態(tài)同步。并非是 hibernate 為了大幅提高系統(tǒng)性能所提供的。

    為了提高使用 hibernate 的性能,除了常規(guī)的一些需要注意的方法比如:

    使用延遲加載、迫切外連接、查詢過(guò)濾等以外,還需要配置 hibernate 的二級(jí)緩存。其對(duì)系統(tǒng)整體性能的改善往往具有立竿見(jiàn)影的效果!

    (經(jīng)過(guò)自己以前作項(xiàng)目的經(jīng)驗(yàn),一般會(huì)有 3~4 倍的性能提高)

    ?

    1.2.2. ????? N+1 次查詢的問(wèn)題

    執(zhí)行條件查詢時(shí), iterate ()方法具有著名的 n+ 1 次查詢的問(wèn)題,也就是說(shuō)在第一次查詢時(shí) iterate 方法會(huì)執(zhí)行滿足條件的查詢結(jié)果數(shù)再加一次( n+1 )的查詢。但是此問(wèn)題只存在于第一次查詢時(shí),在后面執(zhí)行相同查詢時(shí)性能會(huì)得到極大的改善。此方法適合于查詢數(shù)據(jù)量較大的業(yè)務(wù)數(shù)據(jù)。

    但是注意:當(dāng)數(shù)據(jù)量特別大時(shí)(比如流水線數(shù)據(jù)等)需要針對(duì)此持久化對(duì)象配置其具體的緩存策略,比如設(shè)置其存在于緩存中的最大記錄數(shù)、緩存存在的時(shí)間等參數(shù),以避免系統(tǒng)將大量的數(shù)據(jù)同時(shí)裝載入內(nèi)存中引起內(nèi)存資源的迅速耗盡,反而降低系統(tǒng)的性能!!!

    ?

    1.3.?? 使用 hibernate 二級(jí)緩存的其他注意事項(xiàng):

    1.3.1. ????? 關(guān)于數(shù)據(jù)的有效性

    另外, hibernate 會(huì)自行維護(hù)二級(jí)緩存中的數(shù)據(jù),以保證緩存中的數(shù)據(jù)和數(shù)據(jù)庫(kù)中的真實(shí)數(shù)據(jù)的一致性! 無(wú)論何時(shí),當(dāng)你調(diào)用 save() update() ?saveOrUpdate() 方法傳遞一個(gè)對(duì)象時(shí),或使用 load() ?get() list() iterate()? scroll() 方法獲得一個(gè)對(duì)象時(shí) ,? 該對(duì)象都將被加入到 Session 的內(nèi)部緩存中。 ? 當(dāng)隨后 flush() 方法被調(diào)用時(shí),對(duì)象的狀態(tài)會(huì)和數(shù)據(jù)庫(kù)取得同步。

    ?

    也就是說(shuō)刪除、更新、增加數(shù)據(jù)的時(shí)候,同時(shí)更新緩存。當(dāng)然這也包括二級(jí)緩存!

    ?

    只要是調(diào)用 hibernate API 執(zhí)行數(shù)據(jù)庫(kù)相關(guān)的工作。 hibernate 都會(huì)為你自動(dòng)保證 緩存數(shù)據(jù)的有效性!!

    ?

    但是,如果你使用了 JDBC 繞過(guò) hibernate 直接執(zhí)行對(duì)數(shù)據(jù)庫(kù)的操作。此時(shí), Hibernate 不會(huì) / 也不可能自行感知到數(shù)據(jù)庫(kù)被進(jìn)行的變化改動(dòng),也就不能再保證緩存中數(shù)據(jù)的有效性!!

    ?

    這也是所有的 ORM 產(chǎn)品共同具有的問(wèn)題。幸運(yùn)的是, Hibernate 為我們暴露了 Cache 的清除方法,這給我們提供了一個(gè)手動(dòng)保證數(shù)據(jù)有效性的機(jī)會(huì)!!

    一級(jí)緩存,二級(jí)緩存都有相應(yīng)的清除方法。

    ?

    其中二級(jí)緩存提供的清除方法為:

    按對(duì)象 class 清空緩存

    ??????????????? 按對(duì)象 class 和對(duì)象的主鍵 id 清空緩存

    ??????????????? 清空對(duì)象的集合中的緩存數(shù)據(jù)等。

    ???

    1.3.2. ????? 適合使用的情況

    并非所有的情況都適合于使用二級(jí)緩存,需要根據(jù)具體情況來(lái)決定。同時(shí)可以針對(duì)某一個(gè)持久化對(duì)象配置其具體的緩存策略。

    ?

    適合于使用二級(jí)緩存的情況:

    1、 數(shù)據(jù)不會(huì)被第三方修改;

    ?

    一般情況下,會(huì)被 hibernate 以外修改的數(shù)據(jù)最好不要配置二級(jí)緩存,以免引起不一致的數(shù)據(jù)。但是如果此數(shù)據(jù)因?yàn)樾阅艿脑蛐枰痪彺妫瑫r(shí)又有可能被第 3 方比如 SQL 修改,也可以為其配置二級(jí)緩存。只是此時(shí)需要在 sql 執(zhí)行修改后手動(dòng)調(diào)用 cache 的清除方法。以保證數(shù)據(jù)的一致性

    ?

    ? 2 、數(shù)據(jù)大小在可接收范圍之內(nèi);

    ?

    ???? 如果數(shù)據(jù)表數(shù)據(jù)量特別巨大,此時(shí)不適合于二級(jí)緩存。原因是緩存的數(shù)據(jù)量過(guò)大可能會(huì)引起內(nèi)存資源緊張,反而降低性能。

    ?

    如果數(shù)據(jù)表數(shù)據(jù)量特別巨大,但是經(jīng)常使用的往往只是較新的那部分?jǐn)?shù)據(jù)。此時(shí),也可為其配置二級(jí)緩存。但是必須單獨(dú)配置其持久化類的緩存策略,比如最大緩存數(shù)、緩存過(guò)期時(shí)間等,將這些參數(shù)降低至一個(gè)合理的范圍(太高會(huì)引起內(nèi)存資源緊張,太低了緩存的意義不大)。

    ?

    ? 3 、數(shù)據(jù)更新頻率低;

    ?

    ???? 對(duì)于數(shù)據(jù)更新頻率過(guò)高的數(shù)據(jù),頻繁同步緩存中數(shù)據(jù)的代價(jià)可能和 查詢緩存中的數(shù)據(jù)從中獲得的好處相當(dāng),壞處益處相抵消。此時(shí)緩存的意義也不大。

    ?

    ?

    ? 4 、非關(guān)鍵數(shù)據(jù)(不是財(cái)務(wù)數(shù)據(jù)等)

    ?

    ? 財(cái)務(wù)數(shù)據(jù)等是非常重要的數(shù)據(jù),絕對(duì)不允許出現(xiàn)或使用無(wú)效的數(shù)據(jù),所以此時(shí)為了安全起見(jiàn)最好不要使用二級(jí)緩存。

    ? 因?yàn)榇藭r(shí) “正確性”的重要性遠(yuǎn)遠(yuǎn)大于 “高性能”的重要性。

    ?

    2. ???? 目前系統(tǒng)中使用 hibernate 緩存的建議

    1.4.?? 目前情況

    ?一般系統(tǒng)中有三種情況會(huì)繞開(kāi)hibernate執(zhí)行數(shù)據(jù)庫(kù) 操作:

    1、多個(gè)應(yīng)用系統(tǒng)同時(shí)訪問(wèn)一個(gè)數(shù)據(jù)庫(kù)

    ?? 此種情況使用hibernate二級(jí)緩存會(huì)不可避免的造成數(shù)據(jù)不一致的問(wèn)題,

    ?? 此時(shí)要進(jìn)行 詳細(xì)的設(shè)計(jì)。比如在設(shè)計(jì)上避免對(duì)同一數(shù)據(jù)表的同時(shí)的寫(xiě)入操作,

    ?? 使用數(shù)據(jù)庫(kù)各種級(jí)別的鎖定機(jī)制等。

    ?

    2 、動(dòng)態(tài)表相關(guān)

    ???所謂“動(dòng)態(tài)表”是指在系統(tǒng)運(yùn)行時(shí)根據(jù)用戶的操作系統(tǒng)自動(dòng)建立的數(shù)據(jù)表。

    ?? 比如“自定義表單”等屬于用戶自定義擴(kuò)展開(kāi)發(fā)性質(zhì)的功能模塊,因?yàn)榇藭r(shí)數(shù)據(jù)表是運(yùn)行時(shí)建立的,所以不能進(jìn)行hibernate的映射。因此對(duì)它的操作只能是繞開(kāi)hibernate的直接數(shù)據(jù)庫(kù)JDBC操作。

    ??? ??? 如果此時(shí)動(dòng)態(tài)表中的數(shù)據(jù)沒(méi)有設(shè)計(jì)緩存,就不存在數(shù)據(jù)不一致的問(wèn)題。

    ???如果此時(shí)自行設(shè)計(jì)了緩存機(jī)制,則調(diào)用自己的緩存同步方法即可。

    3 、使用 sql對(duì)hibernate持久化對(duì)象表 進(jìn)行批量刪除時(shí)

    ???? 此時(shí) 執(zhí)行批量刪除后,緩存中會(huì)存在已被刪除的數(shù)據(jù)。

    分析:?

    ?? 當(dāng)執(zhí)行了第3條( sql 批量刪除)后,后續(xù)的查詢只可能是以下三種方式:

    a. session.find ()方法:

    根據(jù)前面的總結(jié), find 方法不會(huì)查詢二級(jí)緩存的數(shù)據(jù),而是直接查詢數(shù)據(jù)庫(kù)。

    所以不存在數(shù)據(jù)有效性的問(wèn)題。

    b. 調(diào)用 iterate 方法執(zhí)行條件查詢時(shí):

    根據(jù) iterate 查詢方法的執(zhí)行方式,其每次都會(huì)到數(shù)據(jù)庫(kù)中查詢滿足條件的 id 值,然后再根據(jù)此 id 到緩存中獲取數(shù)據(jù),當(dāng)緩存中沒(méi)有此 id 的數(shù)據(jù)才會(huì)執(zhí)行數(shù)據(jù)庫(kù)查詢;

    如果此記錄已被 sql 直接刪除,則 iterate 在執(zhí)行 id 查詢時(shí)不會(huì)將此 id 查詢出來(lái)。所以,即便緩存中有此條記錄也不會(huì)被客戶獲得,也就不存在不一致的情況。(此情況經(jīng)過(guò)測(cè)試驗(yàn)證)

    ?

    c. get load 方法按 id 執(zhí)行查詢:

    ?

    客觀上此時(shí)會(huì)查詢得到已過(guò)期的數(shù)據(jù)。但是又因?yàn)橄到y(tǒng)中執(zhí)行sql批量刪除一般是

    針對(duì)中間關(guān)聯(lián)數(shù)據(jù)表,對(duì)于

    中間關(guān)聯(lián)表的查詢一般都是采用條件查詢 , id 來(lái)查詢某一條關(guān)聯(lián)關(guān)系的幾率很低 , 所以此問(wèn)題也不存在 !

    ?

    ? ? ? 如果某個(gè)值對(duì)象確實(shí)需要按 id 查詢一條關(guān)聯(lián)關(guān)系 , 同時(shí)又因?yàn)閿?shù)據(jù)量大使用 sql 執(zhí)行批量刪除。當(dāng)滿足此兩個(gè)條件時(shí) , 為了保證按 id 的查詢得到正確的結(jié)果 , 可以使用手動(dòng)清楚二級(jí)緩存中此對(duì)象的數(shù)據(jù)的方法 !!

    ( 此種情況出現(xiàn)的可能性較小 )

    ?

    1.5.?? 建議

    1 、建議不要使用 sql 直接執(zhí)行數(shù)據(jù)持久化對(duì)象的數(shù)據(jù)的更新,但是可以執(zhí)行 批量刪除。(系統(tǒng)中需要批量更新的地方也較少)

    ?

    2 、如果必須使用 sql 執(zhí)行數(shù)據(jù)的更新,必須清空此對(duì)象的緩存數(shù)據(jù)。調(diào)用

    SessionFactory.evict(class)

    SessionFactory.evict(class,id)

    等方法。

    ?

    3 、在批量刪除數(shù)據(jù)量不大的時(shí)候可以直接采用 hibernate 的批量刪除,這樣就不存在繞開(kāi) hibernate 執(zhí)行 sql 產(chǎn)生的緩存數(shù)據(jù)一致性的問(wèn)題。

    ?

    4 、不推薦采用 hibernate 的批量刪除方法來(lái)刪除大批量的記錄數(shù)據(jù)。

    原因是 hibernate 的批量刪除會(huì)執(zhí)行 1 條查詢語(yǔ)句外加 滿足條件的 n 條刪除語(yǔ)句。而不是一次執(zhí)行一條條件刪除語(yǔ)句!!

    當(dāng)待刪除的數(shù)據(jù)很多時(shí)會(huì)有很大的性能瓶頸!!!如果批量刪除數(shù)據(jù)量較大 , 比如超過(guò) 50 , 可以采用 JDBC 直接刪除。這樣作的好處是只執(zhí)行一條 sql 刪除語(yǔ)句 , 性能會(huì)有很大的改善。同時(shí),緩存數(shù)據(jù)同步的問(wèn)題 , 可以采用 hibernate 清除二級(jí)緩存中的相關(guān)數(shù)據(jù)的方法。

    調(diào)用 SessionFactory.evict(class) SessionFactory.evict(class,id) 等方法。

    ?

    所以說(shuō),對(duì)于一般的應(yīng)用系統(tǒng)開(kāi)發(fā)而言(不涉及到集群,分布式數(shù)據(jù)同步問(wèn)題等),因?yàn)橹辉谥虚g關(guān)聯(lián)表執(zhí)行批量刪除時(shí)調(diào)用了 sql 執(zhí)行,同時(shí)中間關(guān)聯(lián)表一般是執(zhí)行條件查詢不太可能執(zhí)行按 id 查詢。所以,此時(shí)可以直接執(zhí)行 sql 刪除,甚至不需要調(diào)用緩存的清除方法。這樣做不會(huì)導(dǎo)致以后配置了二級(jí)緩存引起數(shù)據(jù)有效性的問(wèn)題。

    ?

    退一步說(shuō),即使以后真的調(diào)用了按 id 查詢中間表對(duì)象的方法,也可以通過(guò)調(diào)用清除緩存的方法來(lái)解決。

    ?

    4、具體的配置方法?

    根 據(jù)我了解的很多hibernate的使用者在調(diào)用其相應(yīng)方法時(shí)都迷信的相信“hibernate會(huì)自行為我們處理性能的問(wèn)題”,或者“hibernate 會(huì)自動(dòng)為我們的所有操作調(diào)用緩存”,實(shí)際的情況是hibernate雖然為我們提供了很好的緩存機(jī)制和擴(kuò)展緩存框架的支持,但是必須經(jīng)過(guò)正確的調(diào)用其才有 可能發(fā)揮作用!!所以造成很多使用hibernate的系統(tǒng)的性能問(wèn)題,實(shí)際上并不是hibernate不行或者不好,而是因?yàn)槭褂谜邲](méi)有正確的了解其使 用方法造成的。相反,如果配置得當(dāng)hibernate的性能表現(xiàn)會(huì)讓你有相當(dāng)“驚喜的”發(fā)現(xiàn)。下面我講解具體的配置方法.

    ?ibernate提供了二級(jí)緩存的接口:
    net.sf.hibernate.cache.Provider,
    同時(shí)提供了一個(gè)默認(rèn)的 實(shí)現(xiàn)net.sf.hibernate.cache.HashtableCacheProvider,
    也可以配置 其他的實(shí)現(xiàn) 比如ehcache,jbosscache等。

    具體的配置位置位于hibernate.cfg.xml文件中
    <property name="hibernate.cache.use_query_cache">true</property>
    <property name="hibernate.cache.provider_class">net.sf.hibernate.cache.HashtableCacheProvider</property>

    很多的hibernate使用者在 配置到 這一步 就以為 完事了,
    注 意:其實(shí)光這樣配,根本 就沒(méi)有使用hibernate的二級(jí)緩存。同時(shí)因?yàn)樗麄冊(cè)谑褂胔ibernate時(shí)大多時(shí)候是馬上關(guān)閉session,所以,一級(jí)緩存也沒(méi)有起到任何作 用。結(jié)果就是沒(méi)有使用任何緩存,所有的hibernate操作都是直接操作的數(shù)據(jù)庫(kù)!!性能可以想見(jiàn)。

    正確的辦法是除了以上的配置外還應(yīng)該配置每一個(gè)vo對(duì)象的具體緩存策略,在影射文件中配置。例如:

    <hibernate-mapping>
    <class name="com.sobey.sbm.model.entitySystem.vo.DataTypeVO" table="dcm_datatype">
    <cache usage="read-write"/>
    <id name="id" column="TYPEID" type="java.lang.Long">
    <generator class="sequence"/>
    </id>

    <property name="name" column="NAME" type="java.lang.String"/>
    <property name="dbType" column="DBTYPE" type="java.lang.String"/>
    </class>
    </hibernate-mapping>


    關(guān)鍵就是這個(gè)<cache usage="read-write"/>,其有幾個(gè)選擇
    read-only,read-write,transactional,等
    然后在執(zhí)行查詢時(shí) 注意了 ,如果是條件查詢,或者返回所有結(jié)果的查詢,此時(shí)session.find()方法 不會(huì)獲取緩存中的數(shù)據(jù)。只有調(diào)用query.iterate()方法時(shí)才會(huì)調(diào)緩存的數(shù)據(jù)。

    同時(shí) get 和 load方法 是都會(huì)查詢緩存中的數(shù)據(jù) .

    對(duì)于不同的緩存框架具體的配置方法會(huì)有不同,但是大體是以上的配置

    (另外,對(duì)于支持事務(wù)型,以及支持集群的環(huán)境的配置我會(huì)爭(zhēng)取在后續(xù)的文章中中 發(fā)表出來(lái))

    ?

    3. ???? 總結(jié)

    總之是根據(jù)不同的業(yè)務(wù)情況和項(xiàng)目情況對(duì) hibernate 進(jìn)行有效的配置和正確的使用,揚(yáng)長(zhǎng)避短。不存在適合于任何情況的一個(gè)“萬(wàn)能”的方案。

    以上結(jié)論及建議均建立在自己在對(duì) Hibernate 2.1.2 中的測(cè)試結(jié)果以及以前的項(xiàng)目經(jīng)驗(yàn)的基礎(chǔ)上。如有謬處,請(qǐng)打家提出指正:)!

    最后,祝大家 新年快樂(lè)!!在新的一年里 取得人生的進(jìn)步!!!

    posted on 2006-08-22 09:37 保爾任 閱讀(174) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     

    <2025年7月>
    293012345
    6789101112
    13141516171819
    20212223242526
    272829303112
    3456789

    常用鏈接

    留言簿(4)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 免费一级不卡毛片| 日韩毛片免费一二三| 日韩免费高清大片在线| 日韩一卡2卡3卡4卡新区亚洲| 亚洲AV无码专区在线电影成人| 国产精品成人免费一区二区| 亚洲一区二区免费视频| 久草在视频免费福利| 亚洲五月综合缴情婷婷| 黄+色+性+人免费| 亚洲sss综合天堂久久久| 成人免费a级毛片无码网站入口| 久久亚洲精品国产精品婷婷| 成人一a毛片免费视频| 亚洲熟妇AV一区二区三区宅男| 国产青草视频在线观看免费影院| 亚洲A∨精品一区二区三区下载| 国产又黄又爽又刺激的免费网址| 免费大片av手机看片| 色噜噜亚洲精品中文字幕| 无码人妻AV免费一区二区三区| 亚洲欧洲日本天天堂在线观看| 免费精品人在线二线三线区别| 亚洲av成人一区二区三区观看在线 | 国产女高清在线看免费观看 | 精品国产污污免费网站入口| 亚洲熟女一区二区三区| 9420免费高清在线视频| 国产精品亚洲一区二区麻豆| 亚洲精品高清在线| 亚洲视频在线免费观看| 亚洲日韩AV一区二区三区中文| 亚洲成a人在线看天堂无码| 免费毛片a线观看| 亚洲乱亚洲乱妇24p| 亚洲熟妇av一区二区三区| 亚洲成人免费网站| 免费中文字幕视频| 亚洲视频在线观看地址| 日韩免费高清视频网站| 久久大香香蕉国产免费网站 |