資料庫物件的緩衝策略

來源:互聯網
上載者:User
前言
本文探討Jive(曾經開源的Java論壇)和Hibernate(Java開源持久層)的資料庫物件的緩衝策略,並闡述作者本人的Lightor(Java開源持久層)採用的資料庫物件緩衝策略。
本文的探討基於以前開源的Jive代碼,Hibernate2.1.7源碼,和作者本人的Lightor代碼。
本文用ID (Identifier的縮寫)來代表資料記錄的關鍵字。
資料物件查詢一般分為兩種:條件查詢,返回一個滿足條件的資料對象列表; ID查詢,返回ID對應的資料對象。
本文主要探討“條件查詢”和“ID查詢”這兩種情況的緩衝策略。
本文只探討一個JVM內的資料緩衝策略,不涉及分布式緩衝;本文只探討對應單表的資料對象的緩衝,不涉及關聯表對象的情況。

一、Jive的緩衝策略
1.Jive的緩衝策略的流程說明:
(1)條件查詢的時候,Jive用 select id from table_name where …. (只選擇ID欄位)這樣的SQL語句查詢資料庫,來獲得一個ID列表。
(2) Jive根據ID列表中的每個ID,首先查看緩衝中是否存在對應ID的資料對象:如果存在,那麼直接取出,加入到 結果清單中;如果不存在,那麼通過一條select * from table_name where id = {ID value} 這樣的SQL查詢資料庫,取出對應的資料對象,放入到結果清單,並把這個資料對象按照ID放入到緩衝中。
(3) ID查詢的時候,Jive執行類似第(2)步的過程,先從緩衝中尋找該ID,查不到,再查詢資料庫,然後把結果放入到緩衝。
(4) 刪除、更新、增加資料的時候,同時更新緩衝。
2.Jive緩衝策略的優點:
(1) ID查詢的時候,如果該ID已經存在於緩衝中,那麼可以直接取出。節省了一條資料庫查詢。
(2) 當多次條件查詢的結果集相交的情況下,交集裡面的資料對象不用重複從資料庫整個擷取,直接從緩衝中擷取即可。
比如,第一次查詢的ID列表為{1, 2},然後根據ID列表的ID從資料庫中一個一個取出資料對象,結果集為{a(id = 1),  b(id = 2)}。
下一次查詢的ID列表為{2, 3},由於ID = 2的資料對象已經存在於緩衝中,那麼只要從資料庫中取出ID = 3的資料對象即可。
3.Jive緩衝策略的缺點:
(1) 在根據條件尋找資料對象列表的過程中,DAO的第(1)步用來獲得ID列表的那一次資料庫查詢,是必不可少的。
(2) 如果第(1)步返回的ID列表中有n個ID,在最壞的命中率(緩衝中一個對應ID都沒有)情況下,Jive還要再查詢n次資料庫。最壞情況下,共需要n + 1資料庫查詢。

二、Hibernate的二級緩衝策略
Hibernate用Session類封裝了資料庫連接從開啟到關閉的過程。
Session內部維護一個資料對象集合,包括了本Session內選取的、操作的資料對象。這稱為Session內部緩衝,是Hibernate的第一級最快緩衝,屬於Hibernate的既定行為,不需要進行配置(也沒有辦法配置 :-)。
Session的生命期很短,存在於Session內部的第一級最快緩衝的生命期當然也很短,命中率自然也很低。當然,這個Session內部緩衝的主要作用是保持Session內部資料狀態同步。
如果需要跨Session的命中率較高的全域緩衝,那麼必須對Hibernate進行二級緩衝配置。一般來說,同樣資料類型(Class)的資料對象,共用一個二級緩衝(或其中的同一塊)。
1.Hibernate二級緩衝策略的流程說明:
(1)條件查詢的時候,總是發出一條select * from table_name where …. (選擇所有欄位)這樣的SQL語句查詢資料庫,一次獲得所有的資料對象。
(2) 把獲得的所有資料對象根據ID放入到第二級緩衝中。
(3) 當Hibernate根據ID訪問資料對象的時候,首先從Session一級緩衝中查;查不到,如果配置了二級緩衝,那麼從二級緩衝中查;查不到,再查詢資料庫,把結果按照ID放入到緩衝。
(4) 刪除、更新、增加資料的時候,同時更新緩衝。

2.Hibernate二級緩衝策略的優點:
(1) 具有Jive緩衝策略同樣的第(1)條優點:ID查詢的時候,如果該ID已經存在於緩衝中,那麼可以直接取出。節省了一條資料庫查詢。
(2) 不具有Jive緩衝策略的第(2)條缺點,即hibernate不會有最壞情況下的 n + 1次資料庫查詢。
3.Hibernate二級緩衝策略的缺點:
(1) 同Jive緩衝策略的第(1)條缺點一樣,條件查詢的時候,第(1)步的資料庫查詢語句是不可少的。而且Hibernate選擇所有的欄位,比只選擇ID欄位花費的時間和空間都多。
(2) 不具備Jive緩衝策略的第(2)條優點。條件查詢的時候,必須把資料庫物件從資料庫中整個取出,即使該資料庫的ID已經存在於緩衝中。

三、Hibernate的Query緩衝策略
可以看到,Jive緩衝和Hibernate的二級緩衝策略,都只是針對於ID查詢的緩衝策略,對於條件查詢則毫無作用。(儘管Jive緩衝的第(2)個優點,能夠避免重複從資料庫擷取同一個ID對應的資料對象,但select id from …這條資料庫查詢是每次條件查詢都必不可少的)。
為此,Hibernate提供了針對條件查詢的Query緩衝。
1.Hibernate的Query緩衝策略的流程說明:
(1) 條件查詢的請求一般都包括如下資訊:SQL, SQL需要的參數,記錄範圍(起始位置rowStart,最大記錄個數maxRows),等。
(2) Hibernate首先根據這些資訊組成一個Query Key,根據這個Query Key到Query緩衝中尋找對應的結果清單。如果存在,那麼返回這個結果清單;如果不存在,查詢資料庫,擷取結果清單,把整個結果清單根據Query Key放入到Query緩衝中。
(3) Query Key中的SQL涉及到一些表名,如果這些表的任何資料發生修改、刪除、增加等操作,這些相關的Query Key都要從緩衝中清空。
2.Hibernate的Query緩衝策略的優點
(1) 條件查詢的時候,如果Query Key已經存在於緩衝,那麼不需要再查詢資料庫。命中的情況下,一次資料庫查詢也不需要。
3.Hibernate的Query緩衝策略的缺點
(1) 條件查詢涉及到的表中,如果有任何一條記錄增加、刪除、或改變,那麼緩衝中所有和該表相關的Query Key都會失效。
比如,有這樣幾組Query Key,它們的SQL裡面都包括table1。
SQL = select * from table1 where c1 = ? ….,  parameter = 1, rowStart = 11, maxRows = 20.
SQL = select * from table1 where c1 = ? ….,  parameter = 1, rowStart = 21, maxRows = 20.
SQL = select * from table1 where c1 = ? …..,  parameter = 2, rowStart = 11, maxRows = 20.
SQL = select * from table1 where c1 = ? …..,  parameter = 2, rowStart = 11, maxRows = 20.
SQL = select * from table1 where c2 = ? ….,  parameter = ‘abc’, rowStart = 11, maxRows = 20.

當table1的任何資料對象(任何欄位)改變、增加、刪除的時候,這些Query Key對應的結果集都不能保證沒有發生變化。
很難做到根據資料對象的改動精確判斷哪些Query Key對應的結果集受到影響。最簡單的實現方法,就是清空所有SQL包含table1的Query Key。

(2) Query緩衝中,Query Key對應的是資料對象列表,假如不同的Query Key對應的資料對象列表有交集,那麼,交集部分的資料對象就是重複儲存的。
比如,Query Key 1對應的資料對象列表為{a(id = 1), b(id = 2)},Query Key 2對應的資料對象列表為{a(id = 1), c(id = 3)},這個a就在兩個List同時存在了兩份。

4.二級緩衝和Query緩衝同步的困惑
假如,Query緩衝中,一個Query Key對應的結果清單為{a (id = 1) , b (id = 2), c (id = 3)}; 二級緩衝裡面有也id = 1對應的資料對象a。
這兩個資料對象a之間是什麼關係?能夠保持狀態同步嗎?
我閱讀Hibernate的相關源碼,沒有發現兩個緩衝之間的這種同步關係。
或者兩者之間毫無關係。就像我上面所說的,只要表資料發生變化,相關的Query Key都要被清空。所以不用考慮同步問題?

四、Lightor的緩衝策略
Lightor是我做的Java開源持久層架構。Lightor的意思是,Lightweight O/R。Hibernate,JDO,EJB CMP這些持久層架構,都是Layer。Lightor算不上Layer,而只是一個Helper。這裡的O/R意思不是Object/Relational,而是Object/ResultSet的意思。:-)
Lightor的緩衝策略,主要參照Hibernate的緩衝思路,Lightor的緩衝也分為 Query緩衝和ID緩衝。但其中有一點不同,兩者之間並不是毫無聯絡的,而是相互關聯的。
1.Lightor的緩衝策略的流程說明:
(1) 條件查詢的請求一般都包括如下資訊:SQL, 對應SQL的參數,起始記錄位置(rowStart),最大記錄個數(maxRows),等。
(2) Lightor首先根據這些資訊組成一個Query Key,根據這個Query Key到Query緩衝中尋找對應的結果ID列表。注意,這裡擷取的是ID列表。
如果結果ID列表存在於Query緩衝,那麼根據這個ID列表的每個ID,到ID緩衝中取對應的資料對象。如果所有ID對應的資料對象都找到,那個返回這個資料對象結果清單。注意,這裡擷取的是整個資料對象(所有欄位)的列表。
如果結果ID列表不存在於Query緩衝,或者結果ID列表中的某一個ID不存在於ID緩衝,那麼,就查詢資料庫,擷取結果清單。然後,把擷取的每個資料對象按照ID放入到ID緩衝;並組裝成一個ID列表,按照Query Key存放到Query緩衝中。注意,這裡是把ID列表,而不是整個對象列表,放入到Query緩衝中。
(3) ID查詢的時候,Lightor先從ID緩衝中尋找該ID,如果不存在,那麼查詢資料庫,把結果放入ID緩衝。
(4) Query Key中的SQL涉及到一些表名,如果這些表的任何資料發生修改、刪除、增加等操作,這些相關的Query Key都要從緩衝中清空。
2.Lightor的緩衝策略的優點
(1) Lightor的ID緩衝具有Jive緩衝,和Hibernate二級ID緩衝的優點。ID查詢的時候,如果該ID已經存在於緩衝中,那麼可以直接取出。節省了一條資料庫查詢。
(2) Lightor的Query緩衝具有Hibernate的Query緩衝的優點。條件查詢的時候,如果Query Key已經存在於緩衝,那麼不需要再查詢資料庫。命中的情況下,一次資料庫查詢也不需要。
(3) Lightor的Query緩衝中,Query Key對應的是ID列表,而不是資料對象列表,真正的資料對象只存在於ID緩衝中。所以,不同的Query Key對應的ID列表如果有交集,ID對應的資料對象也不會在ID緩衝中重複儲存。
(4) Lightor的緩衝也沒有Jive緩衝的最壞情況n + 1次資料庫查詢缺點。
3.Lightor的緩衝策略的缺點
(1) Lightor的Query緩衝具有Hibernate的Query緩衝的缺點。條件查詢涉及到的表中,如果有任何一條記錄增加、刪除、或改變,那麼緩衝中所有和該表相關的Query Key都會失效。
(2) Lightor的ID緩衝也具有hibernate的二級ID緩衝具有的缺點。條件查詢的時候,即使ID已經存在於緩衝中,也需要重新把資料對象整個從資料庫取出,放入到緩衝中。

五、Query Key的效率
Query緩衝的Query Key的空間和時間開銷比較大。
Query Key裡面存放的東西不少,SQL, 參數,範圍(起始,個數)。
這裡面最大的東西就是SQL。又佔地方,又花時間(hashCode, equals)。
Query Key最關鍵的兩個方法是hashCode和equals,重點是SQL的hashCode和equals。

Lightor的做法是,由於Lightor直接使用SQL,不用HQL、OQL之類,所以推薦盡量使用static final String的SQL,能夠節省空間的和時間,以至於Query Key的效率能夠相當於ID Key的效率。
至於Hibernate的QueryKey,有興趣的讀者可以去下載閱讀Hibernate的各個版本的原始碼,跟蹤一下QueryKey的實現最佳化過程。

六、總結
這裡列一個表,綜合表示Jive, Hibernate, Lightor的緩衝策略的特徵。
     N + 1問題 重複ID緩衝問題 Query緩衝支援
Jive緩衝           有 無 不支援
Hibernate緩衝 無 有 支援
Lightor緩衝 無 有 支援

註:
“重複ID緩衝問題”的含義是,每次條件查詢,不是只取ID列表,而是取出完整對象(所有欄位)的列表。這樣,同一個ID對應的資料對象,即使在緩衝中已經存在,也可能被重新放入緩衝。參見相關緩衝的缺點描述。
“重複ID緩衝問題”的負面效應到底有多大,就看你的select id from …(只選擇ID)比你的 select * from … (選擇所有欄位)快多少。主要影響因素是,欄位的個數,欄位值的長度,與資料庫伺服器之間網路傳輸速度。
不管怎麼說,即使選擇所有欄位,也只是一次資料庫查詢。而N + 1問題帶來的可能最壞的負面效應(N + 1次資料查詢)卻是非常大的。
選擇緩衝策略的時候,應根據這些情況發生的機率和正負面效應進行取捨。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.