Oracle記憶體全面分析(3)- Buffer Cache的重要檢視和 共享池(Shared pool)
1.1.3.3. Buffer Cache的重要檢視
關於Buffer Cache,oracle提供一些重要檢視,用於查詢關於Buffer Cache的重要資訊,為調整Buffer Cache、提高效能提供參考。下面一一介紹它們
· v$db_cache_advice
上面我們提到了Oracle的建議器,其中有一個針對Buffer Cache的建議器。在我們設定了引數db_cache_advice為TRUE後,經過一段時間的系統執行,Oracle收集到相關統計資料,並根據一定的數學模型,預測出DB_CACHE_SIZE在不同大小情況的效能資料。我們就可以由檢視V$DB_CACHE_ADVICE查出這些資料,並根據這些資料調整DB_CACHE_SZIE,使系統性能最優。
下面是關於這個檢視的結構描述:
欄位 |
資料型別 |
描述 |
ID |
NUMBER |
緩衝池標識號(從1到8,1-6對應於DB_nK_CACHE_SIZE,DB_CACHE_SIZE與系統標準塊尺寸的序號相關,如DB_BLOCK_SIZE為8K,則DB_CACHE_SIZE的標識號為3(2,4,8…)。7是DB_KEEP_CACHE_SIZE,8是DB_RECYCLE_CACHE_SIZE) |
NAME |
VARCHAR2(20) |
緩衝池名稱 |
BLOCK_SIZE |
NUMBER |
緩衝池塊尺寸(位元組為單位) |
ADVICE_STATUS |
VARCHAR2(3) |
建議器狀態:ON表示建議器在執行;OFF表示建議器已經關閉。當建議器關閉了,檢視中的資料是上一次開啟所統計得出的。 |
SIZE_FOR_ESTIMATE |
NUMBER |
預測效能資料的Cache大小(M為單位) |
SIZE_FACTOR |
NUMBER |
預測的Cache大小因子(即與當前大小的比例) |
BUFFERS_FOR_ESTIMATE |
NUMBER |
預測效能資料的Cache大小(緩衝塊數) |
ESTD_PHYSICAL_READ_FACTOR |
NUMBER |
這一緩衝大小時,物理讀因子,它是如果緩衝大小為SIZE_FOR_ESTIMATE時,建議器預測物理讀數與當前實際物理讀數的比率值。如果當前物理讀數為0,這個值為空。 |
ESTD_PHYSICAL_READS |
NUMBER |
如果緩衝大小為SIZE_FOR_ESTIMATE時,建議器預測物理讀數。 |
下面是從這個檢視中查詢出來的資料:
SQL> select size_for_estimate, estd_physical_read_factor, estd_physical_reads
2 from v$db_cache_advice
3 where name = 'DEFAULT';
SIZE_FOR_ESTIMATE ESTD_PHYSICAL_READ_FACTOR ESTD_PHYSICAL_READS
----------------- ------------------------- -------------------
16 2.0176 6514226
32 1.7403 5619048
48 1.5232 4917909
64 1.3528 4367839
80 1.2698 4099816
96 1.1933 3852847
112 1.1443 3694709
128 1.1007 3553685
144 1.0694 3452805
160 1.0416 3362964
176 1.0175 3285085
192 1 3228693
208 0.9802 3164754
224 0.9632 3109920
240 0.9395 3033427
256 0.8383 2706631
272 0.7363 2377209
288 0.682 2202116
304 0.6714 2167888
320 0.6516 2103876
20 rows selected
當前我們的DB_CACHE_SIZE為192M,可以看到,它的物理讀因子為1,物理讀數為3228693。那麼如何根據這些資料調整DB_CACHE_SIZE呢?給出一個方法,找到變化率較平緩的點作為採用值。因為建議器做預測是,DB_CACHE_SIZE的預測值的增長步長是相同的,是16M。我們按照這一步長增加DB_CACHE_SIZE,如果每次增加物理讀降低都很明顯,就可以繼續增加,直到物理讀降低不明顯,說明繼續增加DB_CACHE_SIZE沒有太大作用。當然,效能和可用資源是天平的兩端,你需要根據自己系統的實際情況調整。
上面的例子中,我們可以考慮將DB_CACHE_SIZE調整到288M。因為在288M之前,物理讀因子變化都比較大,而從288M到304M以後,這個因子變化趨緩。用一個二維圖可以更容易看出這個變化來:
這一檢視作為調整DB_CACHE_SIZE以提高效能有很大參考價值。但衡量Buffer Cache是否合適的重要指標還是我們前面提到的快取命中率(Buffer Hit),而影響快取命中率往往還有其他因素,如效能極差的SQL語句。
· V$BUFFER_POOL
這一檢視顯示了當前例項中所有緩衝池的資訊。它的結構如下:
欄位 |
資料型別 |
描述 |
ID |
NUMBER |
緩衝池ID,和上面檢視描述相同。 |
NAME |
VARCHAR2(20) |
緩衝池名稱 |
BLOCK_SIZE |
NUMBER |
緩衝池塊尺寸(位元組為單位) |
RESIZE_STATE |
VARCHAR2(10) |
緩衝池當前狀態。 STATIC:沒有被正在調整大小 ALLOCATING:正在分配記憶體給緩衝池(不能被使用者取消) ACTIVATING:正在建立新的快取塊(不能被使用者取消) SHRINKING:正在刪除快取塊(能被使用者取消) |
CURRENT_SIZE |
NUMBER |
緩衝池大小(M為單位) |
BUFFERS |
NUMBER |
當前快取塊數 |
TARGET_SIZE |
NUMBER |
如果正在調整緩衝池大小(即狀態不為STATIC),這記錄了調整後的大小(M為單位)。如果狀態為STATIC,這個值和當前大小值相同。 |
TARGET_BUFFERS |
NUMBER |
如果正在調整緩衝池大小(即狀態不為STATIC),這記錄了調整後的快取塊數。否則,這個值和當前快取塊數相同。 |
PREV_SIZE |
NUMBER |
前一次調整的緩衝池大小。如果從來沒有調整過,則為0。 |
PREV_BUFFERS |
NUMBER |
前一次調整的快取塊數。如果從來沒有調整過,則為0。 |
LO_BNUM |
NUMBER |
9i後已經廢棄欄位 |
HI_BNUM |
NUMBER |
9i後已經廢棄欄位 |
LO_SETID |
NUMBER |
9i後已經廢棄欄位 |
HI_SETID |
NUMBER |
9i後已經廢棄欄位 |
SET_COUNT |
NUMBER |
9i後已經廢棄欄位 |
· v$buffer_pool_statistics
V$BUFFER_POOL_STATISTICS檢視記錄了所有緩衝池的統計資料。它的結構如下:
欄位 |
資料型別 |
描述 |
ID |
NUMBER |
緩衝池ID,和上面檢視描述相同。 |
NAME |
VARCHAR2(20) |
緩衝池名稱 |
SET_MSIZE |
NUMBER |
緩衝池中快取塊的最大數 |
CNUM_REPL |
NUMBER |
在置換列表中的快取塊數 |
CNUM_WRITE |
NUMBER |
在寫列表中的快取塊數 |
CNUM_SET |
NUMBER |
當前的快取塊數 |
BUF_GOT |
NUMBER |
讀取過的快取塊數 |
SUM_WRITE |
NUMBER |
被寫過的快取塊數 |
SUM_SCAN |
NUMBER |
被掃描過的快取塊數 |
FREE_BUFFER_WAIT |
NUMBER |
等待空閒塊統計數 |
WRITE_COMPLETE_WAIT |
NUMBER |
等待完成寫統計數 |
BUFFER_BUSY_WAIT |
NUMBER |
忙(正在被使用)等待統計數 |
FREE_BUFFER_INSPECTED |
NUMBER |
確認了的空閒快取塊數(即可用的) |
DIRTY_BUFFERS_INSPECTED |
NUMBER |
確認了的髒快取塊數 |
DB_BLOCK_CHANGE |
NUMBER |
被修改過的資料塊數 |
DB_BLOCK_GETS |
NUMBER |
讀取過的資料塊數 |
CONSISTENT_GETS |
NUMBER |
一致性讀統計數 |
PHYSICAL_READS |
NUMBER |
物理讀統計數 |
PHYSICAL_WRITES |
NUMBER |
物理寫統計數 |
檢視當前的Buffer Cache命中率:
SQL> select 1-(physical_reads)/(consistent_gets+db_block_gets)
2 from v$buffer_pool_statistics;
1-(PHYSICAL_READS)/(CONSISTENT
------------------------------
0.967658520581074
SQL>
· v$bh
這一檢視在深入定位緩衝區問題時很有用。它記錄了緩衝區中所有資料塊物件。粒度非常細。這個檢視最初的目的是用於OPS(Oracle Parallel Server Oracle平行伺服器,9i後稱為RAC)的,是用於保證RAC中各個節點的資料一致性的。但是,我們可以通過它來查詢Buffer Cache的使用情況,找出大量消耗Buffer Cache的物件。下面的語句就可以完成這一工作:
SQL> column c0 heading 'Owner' format a15
SQL> column c1 heading 'Object|Name' format a30
SQL> column c2 heading 'Number|of|Buffers' format 999,999
SQL> column c3 heading 'Percentage|ofData|Buffer' format 999,999,999
SQL> select
2 owner c0,
3 object_name c1,
4 count(1) c2,
5 (count(1)/(select count(*) from v$bh)) *100 c3
6 from
7 dba_objects o,
8 v$bh bh
9 where
10 o.object_id = bh.objd
11 and
12 o.owner not in ('SYS','SYSTEM')
13 group by
14 owner,
15 object_name
16 order by
17 count(1) desc
18 ;
C0 C1 C2 C3
--------------- ------------------------------ ---------- ----------
PLSQLDEV STANDARD_CITY 17290 72.5860621
DBOWNER MSG_LOG 2 0.00839630
DBOWNER COUNTRY_PK 1 0.00419815
DBOWNER PARAMETER 1 0.00419815
DBOWNER PARAMETER_PK 1 0.00419815
DBOWNER MSG_LOG_IDX1 1 0.00419815
6 rows selected
SQL>
更重要的是,這個檢視記錄的粒度非常細,一條記錄對應了一個數據塊。這對於我們做記憶體問題分析或分析Oracle行為時很有幫助。
下面是這個檢視的結構:
欄位 |
資料型別 |
說明 |
FILE# |
NUMBER |
快取塊對應的資料塊所在的資料檔案號。可以通過檢視DBA_DATA_FILES或V$DBFILES查詢 |
BLOCK# |
NUMBER |
快取塊對應的資料塊編號 |
CLASS# |
NUMBER |
分類編號 |
STATUS |
VARCHAR2(1) |
快取塊的狀態 FREE:空閒,沒有被使用 XCUR:排斥(正在被使用) SCUR:可被共享 CR:一致性讀 READ:正在從磁碟讀入 MREC:處於從儲存介質恢復狀態 IREC:處於例項恢復狀態 |
XNC |
NUMBER |
快取塊上由於和其他例項爭用導致的PCM(Parallel Cache Management並行快取管理)x to null鎖的數量。這一欄位已經被廢棄。 |
LOCK_ELEMENT_ADDR |
RAW(4 | 8) |
快取塊上PCM鎖的地址。如果多個快取塊的PCM鎖地址相同,說明他們被同一鎖鎖住。 |
LOCK_ELEMENT_NAME |
NUMBER |
快取塊上PCM鎖的地址。如果多個快取塊的PCM鎖地址相同,說明他們被同一鎖鎖住。 |
LOCK_ELEMENT_CLASS |
NUMBER |
快取塊上PCM鎖的地址。如果多個快取塊的PCM鎖地址相同,說明他們被同一鎖鎖住。 |
FORCED_READS |
NUMBER |
由於其他例項的PCM鎖鎖住了該快取塊,導致當前例項嘗試重新請求讀該緩衝塊的次數。 |
FORCED_WRITES |
NUMBER |
由於其他例項的PCM鎖鎖住了該快取塊,導致當前例項嘗試重新請求寫該緩衝塊的次數。 |
DIRTY |
VARCHAR2(1) |
髒標誌:Y – 塊被修改過,是髒塊;N – 不是髒塊 |
TEMP |
VARCHAR2(1) |
是否為臨時塊:Y – 是;N – 否。 |
PING |
VARCHAR2(1) |
是否被ping住:Y – 是;N – 否。 |
STALE |
VARCHAR2(1) |
是否是陳舊塊:Y – 是;N – 否。 |
DIRECT |
VARCHAR2(1) |
是否為直接讀寫塊:Y – 是;N – 否。 |
NEW |
VARCHAR2(1) |
欄位被廢棄,始終為N |
OBJD |
NUMBER |
資料塊所屬物件的物件標號,可以查詢dba_objects |
TS# |
NUMBER |
資料塊所在的表空間號,可以查詢v$tablespaces |
1.1.4. 共享池(Shared pool)
SGA中的共享池由庫快取(Library Cache)、字典快取(Dictionary Cache)、用於並行執行訊息的緩衝以及控制結構組成。
Shared Pool的大小由引數SHARED_POOL_SIZE決定。在32位系統中,這個引數的預設值是8M,而64位系統中的預設值位64M。最大為4G。
對於Shared Pool的記憶體管理,是通過修正過的LRU演算法表來實現的。
下面分別介紹Shared Pool的幾個組成部分。
1.1.4.1. 庫快取(Library Cache)
Library Cache中包括共享SQL區(Shared SQL Areas)、PL/SQL儲存過程和包以及控制結構(如鎖、庫快取控制代碼)。
任何使用者都可以訪問共享SQL區(可以通過v$sqlarea訪問,隨後會介紹這個重要檢視)。因此庫快取存在於SGA的共享池中。
· 共享SQL區和私有SQL區
Oracle會為每一條SQL語句執行(每執行一條語句Oracle都會開啟一個遊標)提供一個共享SQL區(Shared SQL Areas)和私有SQL區(Private SQL Areas屬於PGA)。當發現兩個(或多個)使用者都在運行同一SQL語句時,Oracle會重新組織SQL區,使這些使用者能重用共享SQL區。但他們還會在私有SQL區中儲存一份這條SQL語句的拷貝。
一個共享SQL區中儲存了一條語句的解析樹和查詢計劃。在多使用者系統中,Oracle通過為SQL語句使用同一共享SQL區多次執行來節省記憶體。
當一條新的SQL語句被解析時,Oracle從共享池中分配一塊記憶體來儲存共享SQL區。這塊記憶體的大小與這條語句的複雜性相關。如果Shared Pool不夠空間分配給共享SQL區,Oracle將釋放從LRU連結串列中查詢到最近最少使用的記憶體塊,直到有足夠空間給新的語句的共享SQL區。如果Oracle釋放的是一個共享SQL區的記憶體,那麼相應的語句在下次執行時需要再次解析並重新分配共享SQL區。而從解析語句到分配共享SQL區是一個比較消耗CPU的工程。這就是為什麼我們提倡使用繫結變數的原因了。在沒有使用繫結變數時,語句中的變數的數值不同,oracle就視為一條新的語句(9i後可以通過cursor_sharing來控制),重複上面的解析、記憶體分配的動作,將大大消耗系統資源,降低系統性能。
· PL/SQL程式單元
Oracle對於PL/SQL程式單元(儲存過程、函式、包、匿名PL/SQL塊和觸發器)的處理過程和對單個的SQL語句的處理過程相似。它會分配一個共享區來儲存被解析、編譯過的程式單元。同時分配一個私有區域來存放執行程式單元的會話所指定的程式單元的引數值(包括本地變數、全域性變數和包變數——這也叫做包的例項化)和用於執行程式所需的記憶體。如果多個使用者運行同一個程式單元,則他們共享同一個共享區域,並且各自保持一份私有區域,用於使用者會話中指定的變數值。
而一個PL/SQL程式單元中的每條單個SQL語句的處理過程則和上面描述的SQL語句的處理過程相同。要注意一點,儘管這些語句是從PL/SQL程式單元中來的,但是Oracle還是會為這些語句分配一塊共享SQL區,同時為每個使用者分配一個相應的私有SQL區。