1. 程式人生 > >Oracle記憶體全面分析(3)- Buffer Cache的重要檢視和 共享池(Shared pool)

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區。