Oracle資料庫作為一個管理資料的產品,必須能夠認出使用者所提交的管理命令(通常叫做SQL語句),從而進行響應。認出的過程叫做解析SQL語句的過程,響應的過程叫做執行SQL語句的過程。解析是一個相當複雜的過程,它要考慮各種可能的異常情況,比如SQL語句涉及的對象不存在、提交的使用者沒有許可權等。而且,還需要考慮如何執行SQL語句,採用什麼方式去擷取資料等。解析的最終結果是要產生 Oracle自 己內部的執行計畫,從而指導SQL的執行過程。可以看到,解析是一個非常消耗資源的過程。因此,Oracle在解析使用者提交的SQL 陳述式的過程 中,如果對每次出現的新的SQL語句都按照標準流程完整地從頭到尾解析一遍的話,效率太低。尤其隨著並發使用者數量的增加、 資料量的增 加,資料庫的整體效能將直線下降。
Oracle對SQL語句進行了概括和抽象,將SQL語句提煉為兩部分。一部分是SQL語句的靜態部分,也就是SQL語句本身的關鍵詞、所涉及的表名稱以及表的列名等。另一部分是SQL語句的動態部分,也就是SQL語句中的字面值(literal value,即有關表裡的資料部分,比如 where name='hsj'中,hsj就是SQL語句中的字面值,而where name就是SQL語句中的靜態部分)。很明顯,整個資料庫中所包含的對象數量 是有限 的,而表中所包含的資料則是無限的。而正是這無限的資料導致了SQL語句的千變萬化,也就是說,在資料庫處理的所有SQL語句中 ,靜態部 分可以認為數量是有限的,而動態部分則是無限的。而實際上,動態部分對解析的影響相比於靜態部分對解析的影響來說是微乎 其微,也就 是說通常情況下,對於相同的靜態部分的SQL語句來說,不同的動態部分所產生的解析結果(執行計畫)基本都是一樣的(除非 表裡的資料 分布極其不均勻,則有可能導致不同的動態部分產生不同的執行計畫)。這也就為Oracle提高解析SQL語句的效率提供了方向。
Oracle會將使用者提交來的SQL語句都緩衝在記憶體中。每次處理新的一條SQL語句時,都會先在記憶體中查看是否有相同的SQL語句。如果相同則可以減少最重要的解析工作(也就是產生執行計畫),從而節省了大量的CPU資源;反之,如果沒有找到相同的SQL語句,則必須重新從頭到尾進行完整的解析。這部分存放SQL語句的記憶體就叫做共用池。當然,shared pool裡不僅僅是SQL語句,還包括執行計畫、PL/SQL代 碼、 PL/SQL程式的機器碼、管理shared pool的記憶體結構、控制資訊等內容。
如果SQL語句使用了綁定變數(bind variable),也就是用一個變數來替代SQL中的字面值。那麼Oracle在shared pool中尋找到相同的SQL語句的機率相對就很大。比如:
select c1 from t1 where c2=1;
select c1 from t1 where c2=2;
select c1 from t1 where c2=3;
這裡的1、2、3就是SQL中的字面值。如果寫成:
select c1 from t1 where c2=:v1;
這裡的v1就是綁定變數,用來替代上面的1、2、3。解析時使用綁定變數,而在具體執行SQL時,才將字面值傳入。這時,解析就是比較 SQL 陳述式的靜態部分。前面我們已經知道,靜態部分是有限的,很容易就能夠緩衝在記憶體裡,從而找到相同的SQL語句的機率很高。如果沒有使用綁定變數,則就是比較SQL語句的靜態部分和動態部分,而動態部分的變化是無限的,因此這樣的SQL語句很難被緩衝在shared pool 裡。 畢竟記憶體是有限的,不可能把所有的動態部分都緩衝在shared pool裡。不使用綁定變數導致的直接結果就是,找到相同的SQL語句的 機率較 低,導致必須完整地解析SQL語句,也就導致消耗更多的資源。從這裡也可以看出,只有我們使用了綁定變數,才真正遵循了Oracle 引入 shared pool的根本思路,才能夠更有效地利用shared pool。
shared pool的大小由初始化參數shared_pool_size決定。Oracle 10g以後可以不用設定該參數,而只需要指定sga_target,從而由 Oracle 自動決定shared pool的大小尺寸。
在一個很高的層次上來看,shared pool可以分為庫緩衝(library cache)和資料字典緩衝(dictionary cache)。Library cache存放了最近執行的SQL語句、預存程序、函數、解析樹以及執行計畫等。而dictionary cache則存放了在執行SQL語句過程中,所參照的資料 字典的 資訊,包括SQL語句所涉及的表名、表的列、許可權資訊等。dictionary cache裡面的資訊都是以資料行的形式存放的,而不是以資料 塊的形 式存放的,因此也叫做row cache。對於dictionary cache來說,Oracle傾向於將它們一直緩衝在shared pool裡,不會將它們交換 出記憶體, 因此我們不用對它們進行過多的關注。而library cache則是shared pool裡最重要的部分,也是在shared pool中進進出出最活躍 的部分, 需要我們仔細研究。所以,我們在說到shared pool實際上就可以認為是在指library cache
查看本欄目更多精彩內容:http://www.bianceng.cnhttp://www.bianceng.cn/database/Oracle/