1. 程式人生 > >關於shared pool的深入探討

關於shared pool的深入探討

我們看到,在Oracle9i中,Free Lists被劃分為0~254,共255個Bucket。
每個Bucket容納的size範圍
Bucket 0~199 容納size以 4 遞增
Bucket 200~249 容納size以 64 遞增

從Bucket 249開始,Oracle各Bucket步長進一步增加:

Bucket 249: 4012 ~4107 = 96
Bucket 250: 4108 ~8203 = 4096
Bucket 251: 8204 ~16395 = 8192
Bucket 252: 16396~32779 = 16384
Bucket 253: 32780~65547 = 32768
Bucket 254: >=65548

在Oracle9i中,對於小的chunk,Oracle增加了更多的Bucket來管理。0~199共200個Bucket,size以4為步長遞增;200~249共50個Bucket,size以64遞增。這樣每個Bucket中容納的chunk數量大大減少,查詢的效率得以提高。

這就是Oracle9i中shared pool管理的增強,通過這個演算法的改進。Oracle8i中,過大shared pool帶來的栓鎖爭用等效能問題在某種程度上得以解決。

我們繼續把前面的問題展開一下。

其實我們可以從資料庫內部監控shared pool的空間碎片情況。
這涉及到一個內部檢視x$ksmsp

X$KSMSP的名稱含義為: [K]ernal [S]torage [M]emory Management [S]GA Hea[P]
其中每一行都代表著shared pool中的一個chunk.

首先記錄一下測試環境: 

SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.3.0 - Production
PL/SQL Release 9.2.0.3.0 - Production
CORE 9.2.0.3.0 Production
TNS for Linux: Version 9.2.0.3.0 - Production
NLSRTL Version 9.2.0.3.0 – Production

我們看一下x$ksmsp的結構:

SQL> desc x$ksmsp

 Name                                      Null?    Type

 ----------------------------------------- -------- ----------------------------

 ADDR                                                   RAW(4)

 INDX                                                    NUMBER

 INST_ID                                               NUMBER

 KSMCHIDX                                           NUMBER

 KSMCHDUR                                           NUMBER

 KSMCHCOM                                          VARCHAR2(16)

 KSMCHPTR                                           RAW(4)

 KSMCHSIZ                                            NUMBER

 KSMCHCLS                                           VARCHAR2(8)

 KSMCHTYP                                            NUMBER

 KSMCHPAR                                           RAW(4)                                                                   

我們關注以下幾個欄位:

KSMCHCOM是註釋欄位,每個記憶體塊被分配以後,註釋會新增在該欄位中.
x$ksmsp.ksmchsiz代表塊大小

x$ksmsp.ksmchcls列代表型別,主要有四類,說明如下:

free
Free chunks--不包含任何物件的chunk,可以不受限制的被分配.

recr
Recreatable chunks--包含可以被臨時移出記憶體的物件,在需要的時候,這個物件可以被重新建立.例如,許多儲存共享sql程式碼的記憶體都是可以重建的.

freeabl
Freeable chunks--包含session週期或呼叫的物件,隨後可以被釋放.這部分記憶體有時候可以全部或部分提前釋放.但是注意,由於某些物件是中間過程產生的,這些物件不能臨時被移出記憶體(因為不可重建).

perm
Permanent memory chunks--包含永久物件.通常不能獨立釋放.

我們可以通過查詢x$ksmsp檢視來考察shared pool中存在的記憶體片的數量。

不過注意:Oracle的某些版本(如:10.1.0.2)在某些平臺上(如:HP-UX PA-RISC 64-bit)查
詢該檢視可能導致過度的CPU耗用,這是由於bug引起的。

我們看一下測試:

初始啟動資料庫,x$ksmsp中存在2259個chunk

SQL> select count(*) from x$ksmsp;

  COUNT(*)

----------

      2259

執行查詢:

SQL> select count(*) from dba_objects;

  COUNT(*)

----------

     10491

此時shared pool中的chunk數量增加

SQL> select count(*) from x$ksmsp;

  COUNT(*)

----------

      2358

這就是由於shared pool中進行sql解析,請求空間,進而導致請求free空間,分配、分割。從而產生了更多,更細碎的記憶體chunk。由此我們可以看出,如果資料庫系統中存在大量的硬解析,不停請求分配free的shred pool記憶體。除了必須的shared pool latch等競爭外,還不可避免的會導致shared pool中產生更多的記憶體碎片(當然,在記憶體回收時,你可能看到chunk數量減少的情況)。

我們看以下測試:

首先重新啟動資料庫:

SQL> startup force;

ORACLE instance started.

Total System Global Area   47256168 bytes

Fixed Size                          451176 bytes

Variable Size                      29360128 bytes

Database Buffers               16777216 bytes

Redo Buffers                      667648 bytes

Database mounted.

Database opened.

建立一張臨時表用以儲存之前x$ksmsp的狀態:

SQL> CREATE GLOBAL TEMPORARY TABLE e$ksmsp ON COMMIT PRESERVE ROWS AS

  2  SELECT      a.ksmchcom,

  3           SUM (a.CHUNK) CHUNK,

  4           SUM (a.recr) recr,

  5           SUM (a.freeabl) freeabl,

  6           SUM (a.SUM) SUM

  7      FROM (SELECT   ksmchcom, COUNT (ksmchcom) CHUNK,

  8                     DECODE (ksmchcls, 'recr', SUM (ksmchsiz), NULL) recr,

  9                     DECODE (ksmchcls, 'freeabl', SUM (ksmchsiz), NULL) freeabl,

 10                     SUM (ksmchsiz) SUM

 11                FROM x$ksmsp GROUP BY ksmchcom, ksmchcls) a

 12  where 1 = 0

 13  GROUP BY a.ksmchcom;

Table created.

儲存當前shared pool狀態:

SQL> INSERT INTO E$KSMSP

  2  SELECT      a.ksmchcom,

  3           SUM (a.CHUNK) CHUNK,

  4           SUM (a.recr) recr,

  5           SUM (a.freeabl) freeabl,

  6           SUM (a.SUM) SUM

  7      FROM (SELECT   ksmchcom, COUNT (ksmchcom) CHUNK,

  8                     DECODE (ksmchcls, 'recr', SUM (ksmchsiz), NULL) recr,

  9                     DECODE (ksmchcls, 'freeabl', SUM (ksmchsiz), NULL) freeabl,

 10                     SUM (ksmchsiz) SUM

 11                FROM x$ksmsp

 12            GROUP BY ksmchcom, ksmchcls) a

 13  GROUP BY a.ksmchcom

 14  /

41 rows created.

執行查詢:

SQL> select count(*) from dba_objects;

  COUNT(*)

----------

     10492

比較前後shared pool記憶體分配的變化:

SQL> select a.ksmchcom,a.chunk,a.sum,b.chunk,b.sum,(a.chunk - b.chunk) c_diff,(a.sum -b.sum) s_diff

  2  from

  3  (SELECT   a.ksmchcom,

  4           SUM (a.CHUNK) CHUNK,

  5           SUM (a.recr) recr,

  6           SUM (a.freeabl) freeabl,

  7           SUM (a.SUM) SUM

  8      FROM (SELECT   ksmchcom, COUNT (ksmchcom) CHUNK,

  9                     DECODE (ksmchcls, 'recr', SUM (ksmchsiz), NULL) recr,

 10                     DECODE (ksmchcls, 'freeabl', SUM (ksmchsiz), NULL) freeabl,

 11                     SUM (ksmchsiz) SUM

 12                FROM x$ksmsp

 13            GROUP BY ksmchcom, ksmchcls) a

 14  GROUP BY a.ksmchcom) a,e$ksmsp b

 15  where a.ksmchcom = b.ksmchcom and (a.chunk - b.chunk) <>0

 16  /

KSMCHCOM        CHUNK        SUM      CHUNK        SUM     C_DIFF     S_DIFF

---------------- ---------- ---------- ---------- ---------- ---------- ----------

KGL handles              313     102080        302      98416         11       3664

KGLS heap               274     365752        270     360424          4       5328

KQR PO                  389     198548        377     192580         12       5968

free memory               93    2292076         90    2381304          3     -89228

library cache             1005     398284        965     381416         40      16868

sql area                  287     547452        269     490052         18      57400

6 rows selected.                                                                   

我們簡單分析一下以上結果:

首先free memory的大小減少了89228(增加到另外五個元件中),這說明sql解析儲存佔用了一定的記憶體空間。而chunk從90增加為93,這說明記憶體碎片增加了。

在下面的部分中,我會著手介紹一下KGL handles, KGLS heap這兩個非常重要的shared pool中的記憶體結構。

基本命令:

ALTER SESSION SET EVENTS 'immediate trace name LIBRARY_CACHE level LL';

其中LL代表Level級別,對於9.2.0及以後版本,不同Level含義如下:
Level =1 ,轉儲Library cache統計資訊
Level =2 ,轉儲hash table概要
Level =4 ,轉儲Library cache物件,只包含基本資訊
Level =8 ,轉儲Library cache物件,包含詳細資訊(包括child references,pin waiters等)
Level =16,增加heap sizes資訊
Level =32,增加heap資訊

Library cache由一個hash表組成,而hash表是一個由hash buckets組成的陣列。

每個hash bucket都是包含library cache handle的一個雙向連結串列。
Library Cache Handle指向Library Cache Object和一個引用列表。
library cache物件進一步分為:依賴表、子表和授權表等

我們看一下library cache的結構:

通過
ALTER SESSION SET EVENTS 'immediate trace name LIBRARY_CACHE level 4'
獲得以下輸出(這部分資訊來自Oracle8i,Trace檔案可以從www.eygle.com上找到)

第一部分(等價於Level 1):

LIBRARY CACHE STATISTICS:
     
gets hit ratio       pins hit ratio    reloads   invalids namespace
---------- --------- ---------- --------- ---------- ---------- ---------
 619658171 0.9999160 2193292112 0.9999511       9404        380 CRSR
  79698558 0.9998832  424614847 0.9999108      13589          0 TABL/PRCD/TYPE
    163399 0.9979926     163402 0.9978948         16          0 BODY/TYBD
         0 0.0000000          0 0.0000000          0          0 TRGR
        34 0.0294118         35 0.0571429          0          0 INDX
     18948 0.9968862      24488 0.9953855          0          0 CLST
         0 0.0000000          0 0.0000000          0          0 OBJE
         0 0.0000000          0 0.0000000          0          0 PIPE
         0 0.0000000          0 0.0000000          0          0 LOB
         0 0.0000000          0 0.0000000          0          0 DIR
         0 0.0000000          0 0.0000000          0          0 QUEU
         0 0.0000000          0 0.0000000          0          0 OBJG
         0 0.0000000          0 0.0000000          0          0 PROP
         0 0.0000000          0 0.0000000          0          0 JVSC
         0 0.0000000          0 0.0000000          0          0 JVRE
         0 0.0000000          0 0.0000000          0          0 ROBJ
         0 0.0000000          0 0.0000000          0          0 REIP
         0 0.0000000          0 0.0000000          0          0 CPOB
    115071 0.9992179     115071 0.9930999        704          0 EVNT
         0 0.0000000          0 0.0000000          0          0 SUMM
         0 0.0000000          0 0.0000000          0          0 DIMN
         0 0.0000000          0 0.0000000          0          0 CTX
         0 0.0000000          0 0.0000000          0          0 OUTL
         0 0.0000000          0 0.0000000          0          0 RULS
         0 0.0000000          0 0.0000000          0          0 RMGR
         0 0.0000000          0 0.0000000          0          0 UNUSED
         0 0.0000000          0 0.0000000          0          0 PPLN
         0 0.0000000          0 0.0000000          0          0 PCLS
         0 0.0000000          0 0.0000000          0          0 SUBS
         0 0.0000000          0 0.0000000          0          0 LOCS
         0 0.0000000          0 0.0000000          0          0 RMOB
         0 0.0000000          0 0.0000000          0          0 RSMD
 699654181 0.9999117 2618209955 0.9999440      23713        380 CUMULATIVE

這部分資訊也就是v$librarycache中顯示的.

第二部分(等價於Level 2中的輸出): 

LIBRARY CACHE HASH TABLE: size=509 count=354
BUCKET    0:
BUCKET    1:
BUCKET    2: *
BUCKET    3:
BUCKET    4:
BUCKET    5: *
BUCKET    6: *
BUCKET    7:
BUCKET    8: **
BUCKET    9: ***
BUCKET   10: *
BUCKET   11: *
BUCKET   12: ***
……..

BUCKET  103:
BUCKET  104: *
BUCKET  105:
BUCKET  106:
BUCKET  107: ****
BUCKET  108:
BUCKET  109:
BUCKET  110:
BUCKET  111: *
BUCKET  112: **
BUCKET  113:
BUCKET  114:
BUCKET  115:
BUCKET  116: *
BUCKET  117:
BUCKET  118: *****
BUCKET  119:
BUCKET  120: *
BUCKET  121:
BUCKET  122:
BUCKET  123:
BUCKET  124:
BUCKET  125: *
BUCKET  126:
BUCKET  127:
BUCKET  128: *
BUCKET  129:
BUCKET  130: *
BUCKET  131: *
BUCKET  132:
BUCKET  133:
BUCKET  134:
BUCKET  135: *
BUCKET  136:
BUCKET  137:
BUCKET  138:
BUCKET  139: *
BUCKET  140: *
BUCKET  141: *
BUCKET  142:
BUCKET  143: *
BUCKET  144:
BUCKET  145: ***
BUCKET  146:
BUCKET  147: *
BUCKET  148:
BUCKET  149:
BUCKET  150: **
BUCKET  151:
BUCKET  152:
BUCKET  153: *
BUCKET  154:
BUCKET  155:
BUCKET  156:
BUCKET  157:
BUCKET  158:
BUCKET  159:
BUCKET  160:
BUCKET  161:
BUCKET  162:
BUCKET  163:
BUCKET  164: *
BUCKET  165: *
BUCKET  166:
BUCKET  167:
BUCKET  168:
BUCKET  169:
BUCKET  170: **
BUCKET  171:
BUCKET  172: *
BUCKET  173:
BUCKET  174:
BUCKET  175: *
BUCKET  176: *
BUCKET  177:
BUCKET  178:
BUCKET  179:
BUCKET  180:
BUCKET  181: *
BUCKET  182:
BUCKET  183:
BUCKET  184:
BUCKET  185: *
BUCKET  186:
BUCKET  187:
BUCKET  188: **
BUCKET  189:
BUCKET  190: *
BUCKET  191: *
BUCKET  192:
BUCKET  193:
BUCKET  194: *
BUCKET  195: **
BUCKET  196: *
BUCKET  197: **
BUCKET  198: ****
BUCKET  199: *
BUCKET  200: *
……….
BUCKET  509:
BUCKET  510:
BUCKET  511:

在Oracle8i中,Oracle以一個很長的LIBRARY CACHE HASH TABLE來記錄Library Cache的使用情況。"*"代表該Bucket中包含的物件的個數。

在以上輸出中我們看到Bucket 198中包含四個物件.

我們在第三部分中可以找到bucket 198: 

 BUCKET 198:
  LIBRARY OBJECT HANDLE: handle=2c2b4ac4
  name=
SELECT a.statement_id, a.timestamp, a.remarks, a.operation, a.options,
       a.object_node, a.object_owner, a.object_name, a.object_instance,
       a.object_type, a.optimizer, a.search_columns, a.id, a.parent_id,
       a.position, a.cost, a.cardinality, a.bytes, a.other_tag,
       a.partition_start, a.partition_stop, a.partition_id, a.other,
       a.distribution
, ROWID
  FROM plan_table a

  hash=60dd47a1 timestamp=08-27-2004 10:19:28
  namespace=CRSR flags=RON/TIM/PN0/LRG/[10010001]
  kkkk-dddd-llll=0000-0001-0001 lock=0 pin=0 latch=0
  lwt=2c2b4adc[2c2b4adc,2c2b4adc] ltm=2c2b4ae4[2c2b4ae4,2c2b4ae4]
  pwt=2c2b4af4[2c2b4af4,2c2b4af4] ptm=2c2b4b4c[2c2b4b4c,2c2b4b4c]
  ref=2c2b4acc[2c2b4acc,2c2b4acc]
    LIBRARY OBJECT: object=2c0b1430
    type=CRSR flags=EXS[0001] pflags= [00] status=VALD load=0
    CHILDREN: size=16
    child#    table reference   handle
    ------ -------- --------- --------
         0 2c0b15ec  2c0b15b4 2c2c0d50
    DATA BLOCKS:
    data#     heap  pointer status pins change
    ----- -------- -------- ------ ---- ------
        0 2c362290 2c0b14b4 I/-/A     0 NONE 
  LIBRARY OBJECT HANDLE: handle=2c3675d4
  name=SYS.DBMS_STANDARD
  hash=50748ddb timestamp=NULL
  namespace=BODY/TYBD flags=TIM/SML/[02000000]
  kkkk-dddd-llll=0000-0011-0011 lock=0 pin=0 latch=0
  lwt=2c3675ec[2c3675ec,2c3675ec] ltm=2c3675f4[2c3675f4,2c3675f4]
  pwt=2c367604[2c367604,2c367604] ptm=2c36765c[2c36765c,2c36765c]
  ref=2c3675dc[2c3675dc,2c3675dc]
    LIBRARY OBJECT: object=2c1528e8
    flags=NEX[0002] pflags= [00] status=VALD load=0
    DATA BLOCKS:
    data#     heap  pointer status pins change
    ----- -------- -------- ------ ---- ------
        0 2c367564 2c1529cc I/-/A     0 NONE 
        4 2c15297c        0 -/P/-     0 NONE 
  LIBRARY OBJECT HANDLE: handle=2c347dd8
  name=select pos#,intcol#,col#,spare1 from icol$ where obj#=:1
  hash=fa15ebe3 timestamp=07-28-2004 18:04:43
  namespace=CRSR flags=RON/TIM/PN0/SML/[12010000]
  kkkk-dddd-llll=0000-0001-0001 lock=0 pin=0 latch=0
  lwt=2c347df0[2c347df0,2c347df0] ltm=2c347df8[2c347df8,2c347df8]
  pwt=2c347e08[2c347e08,2c347e08] ptm=2c347e60[2c347e60,2c347e60]
  ref=2c347de0[2c347de0,2c347de0]
    LIBRARY OBJECT: object=2c1cd1a0
    type=CRSR flags=EXS[0001] pflags= [00] status=VALD load=0
    CHILDREN: size=16
    child#    table reference   handle
    ------ -------- --------- --------
         0 2c1cd35c  2c1cd324 2c281678
         1 2c1cd35c  2c352c50 2c0eeb8c
         2 2c1cd35c  2c352c6c 2c2bb05c
    DATA BLOCKS:
    data#     heap  pointer status pins change
    ----- -------- -------- ------ ---- ------
        0 2c2e8c58 2c1cd224 I/-/A     0 NONE 
  LIBRARY OBJECT HANDLE: handle=2c3a6484
  name=SYS.TS$
  hash=bb42852e timestamp=04-24-2002 00:04:15
  namespace=TABL/PRCD/TYPE flags=PKP/TIM/KEP/SML/[02900000]
  kkkk-dddd-llll=0111-0111-0119 lock=0 pin=0 latch=0
  lwt=2c3a649c[2c3a649c,2c3a649c] ltm=2c3a64a4[2c3a64a4,2c3a64a4]
  pwt=2c3a64b4[2c3a64b4,2c3a64b4] ptm=2c3a650c[2c3a650c,2c3a650c]
  ref=2c3a648c[2c0d4b14,2c09353c]
    LIBRARY OBJECT: object=2c3a626c
    type=TABL flags=EXS/LOC[0005] pflags= [00] status=VALD load=0
    DATA BLOCKS:
    data#     heap  pointer status pins change
    ----- -------- -------- ------ ---- ------
        0 2c3a8ea4 2c3a63b0 I/P/A     0 NONE 
        3 2c3a5828        0 -/P/-     0 NONE 
        4 2c3a6300 2c3a5960 I/P/A     0 NONE 
        8 2c3a6360 2c3a4f00 I/P/A     0 NONE 

我們看到這裡包含了四個物件.

我們再來看看Oracle9i中的情況:

LIBRARY CACHE HASH TABLE: size=131072 count=217
Buckets with more than 20 objects:
NONE
Hash Chain Size     Number of Buckets
---------------     -----------------
              0                130855
              1                   217
              2                     0
              3                     0
              4                     0
              5                     0
              6                     0
              7                     0
              8                     0
              9                     0
             10                     0
             11                     0
             12                     0
             13                     0
             14                     0
             15                     0
             16                     0
             17                     0
             18                     0
             19                     0
             20                     0
            >20                     0

Oracle9i中通過新的方式記錄Library Cache的使用狀況.

按不同的Hash Chain Size代表Library Cache中包含不同物件的個數.0表示Free的Bucket,>20表示包含超過20個物件的Bucket的個數.

從以上列表中我們看到,包含一個物件的Buckets有217個,包含0個物件的Buckets有130855個.

我們來驗證一下:

  [[email protected] udump]$ cat hsjf_ora_15800.trc |grep BUCKET|more
  BUCKET 12:
  BUCKET 12 total object count=1
  BUCKET 385:
  BUCKET 385 total object count=1
  BUCKET 865:
  BUCKET 865 total object count=1
  ...

  [[email protected] udump]$ cat hsjf_ora_15800.trc |grep BUCKET|wc -l

  434

  [[email protected] udump]$

434/2 = 217,證實了我們的猜想.

通過HASH TABLE演算法的改進,Oracle Library Cache管理的效率大大提高.

我們進一步來討論一下shared pool的處理:

先進行相應查詢,獲得測試資料: 

[[email protected] udump]$ sqlplus "/ as sysdba"

SQL*Plus: Release 9.2.0.3.0 - Production on Thu Aug 26 10:21:54 2004

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

Connected to:

Oracle9i Enterprise Edition Release 9.2.0.3.0 - Production

With the Partitioning, OLAP and Oracle Data Mining options

JServer Release 9.2.0.3.0 - Production

SQL> connect eygle/eygle

Connected.

SQL> create table emp as select * from scott.emp;

Table created.

SQL>

SQL> connect / as sysdba

Connected.

SQL> startup force;

ORACLE instance started.

Total System Global Area   47256168 bytes

Fixed Size                   451176 bytes

Variable Size              29360128 bytes

Database Buffers           16777216 bytes

Redo Buffers                 667648 bytes

Database mounted.

Database opened.

SQL> set linesize 120

SQL> connect scott/tiger

Connected.

SQL> select * from emp;

EMPNO ENAME      JOB       MGR HIREDATE       SAL       COMM     DEPTNO

---------- ---------- --------- ---------- --------- ---------- ---------- ----------

7369 SMITH      CLERK           7902 17-DEC-80        800                    20

8888 EYGLE      MANAGER              11-AUG-04       9999         10       10

7566 JONES      MANAGER         7839 02-APR-81       2975                   20

7698 BLAKE      MANAGER         7839 01-MAY-81       2850                   30

7782 CLARK      MANAGER         7839 09-JUN-81       2450                   10

7788 SCOTT      ANALYST         7566 19-APR-87       3000                    20

7839 KING       PRESIDENT            17-NOV-81       5000                    10

7876 ADAMS      CLERK           7788 23-MAY-87       1100                    20

7900 JAMES      CLERK           7698 03-DEC-81        950                     30

7902 FORD       ANALYST         7566 03-DEC-81       3000                    20

7934 MILLER     CLERK           7782 23-JAN-82       1300                     10

11 rows selected.

SQL> connect eygle/eygle

Connected.

SQL> select * from emp;

EMPNO ENAME      JOB          MGR HIREDATE     SAL      COMM     DEPTNO

---------- ---------- --------- ---------- --------- ---------- ---------- ----------

7369 SMITH      CLERK           7902 17-DEC-80        800                    20

8888 EYGLE      MANAGER              11-AUG-04       9999         10       10

7566 JONES      MANAGER         7839 02-APR-81       2975                  20

7698 BLAKE      MANAGER         7839 01-MAY-81       2850                  30

7782 CLARK      MANAGER         7839 09-JUN-81       2450                  10

7788 SCOTT      ANALYST         7566 19-APR-87       3000                   20

7839 KING       PRESIDENT            17-NOV-81       5000                   10

7876 ADAMS      CLERK           7788 23-MAY-87       1100                   20

7900 JAMES      CLERK           7698 03-DEC-81        950                    30

7902 FORD       ANALYST         7566 03-DEC-81       3000                   20

7934 MILLER     CLERK           7782 23-JAN-82       1300                    10

11 rows selected.

SQL> select SQL_TEXT,VERSION_COUNT,HASH_VALUE,to_char(HASH_VALUE,'xxxxxxxxxx') HEX,ADDRESS

2  from v$sqlarea where sql_text like 'select * from emp%';

SQL_TEXT             VERSION_COUNT HASH_VALUE HEX         ADDRESS

-------------------- ------------- ---------- ----------- --------

select * from emp                2 2648707557    9de011e5 52D9EA28

SQL> select sql_text,username,ADDRESS,HASH_VALUE,to_char(HASH_VALUE,'xxxxxxxxxx') HEX_HASH_VALUE,CHILD_NUMBER,CHILD_LATCH

2  from v$sql a,dba_users b where a.PARSING_USER_ID = b.user_id and  sql_text like 'select * from emp%';

SQL_TEXT             USERNAME                       ADDRESS  HASH_VALUE HEX_HASH_VA CHILD_NUMBER CHILD_LATCH

-------------------- ------------------------------ -------- ---------- ----------- ------------ -----------

select * from emp    SCOTT                          52D9EA28 2648707557    9de011e5            0           1

select * from emp    EYGLE                          52D9EA28 2648707557    9de011e5            1           1

注意:這裡我們可以看出v$sqlareav$sql兩個檢視的不同之處

v$sql中為每一條sql保留一個條目,而v$sqlarea中根據sql_text進行group by,通過version_count計運算元指標的個數.

我們注意到,這兩條sql語句因為其程式碼完全相同,所以其ADDRESS,HASH_VALUE也完全相同.

這就意味著,這兩條sql語句在shared pool中的儲存位置是相同的(儘管其執行計劃可能不同),程式碼得以共享.

在此過程中Oracle完成sql解析的第一個步驟:語法解析

Oracle進行語法檢查時遵循自右向左,自下向上的原則,如果發現語法錯誤就馬上返回錯誤.

語法檢查通過以後,Oraclesql文字轉換為相應的ASCII數值,然後根據數值通過Hash函式計算其HASH_VALUE

shared pool中尋找是否存在相同的sql語句,如果存在,則進入下一步驟;如果不存在則嘗試獲取shared pool latch

請求記憶體,儲存該sql程式碼

在這裡有一個問題需要說明一下:

因為大小寫字母的ascii值是不同的,所以Oracle會把大小寫不同的程式碼作為不同的sql來處理,我們看一下測試:

SQL> select * from scott.dept;

DEPTNO DNAME          LOC

---------- -------------- -------------

10 ACCOUNTING     NEW YORK

20 RESEARCH       DALLAS

30 SALES          CHICAGO

40 OPERATIONS     BOSTON

SQL> select * from scott.DEPT;

DEPTNO DNAME          LOC

---------- -------------- -------------

10 ACCOUNTING     NEW YORK

20 RESEARCH       DALLAS

30 SALES          CHICAGO

40 OPERATIONS     BOSTON

SQL> col sql_text for a30

SQL> select sql_text,hash_value from v$sql where sql_text like 'select * from scott%';

SQL_TEXT                       HASH_VALUE

------------------------------ ----------

select * from scott.DEPT       4096614922

select * from scott.dept       2089404358

我們注意到,僅只大小寫的不同使得原本相同的sql語句變成了兩條"不同的程式碼"

所以從這裡我們可以看出,sql的規範編寫非常重要.

完成這一個步驟以後,Oracle需要進行的是語義分析:

在此步驟中,Oracle需要驗證物件是否存在,相關使用者是否具有許可權,引用的是否是相同的物件...

對於我們第一個查詢,實際上emp表來自不同的使用者,那麼sql的執行計劃也就不同了

當然影響sql執行計劃的因素還有很多,包括優化器模式等

SQL> select a.*,to_char(to_hash,'xxxxxxxxxx') Hex_HASH_VALUE

2  from V$OBJECT_DEPENDENCY  a where to_name='EMP';

FROM_ADD  FROM_HASH TO_OWNER             TO_NAME              TO_ADDRE    TO_HASH    TO_TYPE HEX_HASH_VA

-------- ---------- -------------------- -------------------- -------- ---------- ---------- -----------

52D9EA28 2648707557 SCOTT               EMP                  52D9DEBC  828228010          2    315dc1aa

52D9EA28 2648707557 EYGLE               EMP                  52D82E58 1930491453          2    7310f63d

SQL> ALTER SESSION SET EVENTS 'immediate trace name LIBRARY_CACHE level 1';

Session altered.

SQL> ALTER SESSION SET EVENTS 'immediate trace name LIBRARY_CACHE level 2';

Session altered.

SQL> ALTER SESSION SET EVENTS 'immediate trace name LIBRARY_CACHE level 4';

Session altered.

SQL> ALTER SESSION SET EVENTS 'immediate trace name LIBRARY_CACHE level 8';

Session altered.

SQL> ALTER SESSION SET EVENTS 'immediate trace name LIBRARY_CACHE level 16';

Session altered.

SQL> ALTER SESSION SET EVENTS 'immediate trace name LIBRARY_CACHE level 32';

Session altered.

SQL> ALTER SESSION SET EVENTS 'immediate trace name LIBRARY_CACHE level 100';

Session altered.                     

此處在不同級別對shared pool進行轉儲.

在轉向trace檔案之前,我們通過下圖來看一下Library CACHE的結構:

 hash.jpg

見上傳圖片

Library Cache Handle指向Library Cache Object,含物件名,namespace,時間戳,引用列表,鎖定物件及pin物件列表等.

我們從dump檔案中看看具體的資訊,由以上v$sql檢視我們得到以上查詢的hash_value為9de011e5,ADDRESS為52D9EA28

在bucket 4851中,我們找到了select * from emp 這條sql語句. 

BUCKET 4581:

  LIBRARY OBJECT HANDLE: handle=52d9ea28

  name=select * from emp

  hash=9de011e5 timestamp=08-26-2004 10:24:43

==>這個hash正是v$sql中該sql語句的hash_value值   

  namespace=CRSR flags=RON/TIM/PN0/SML/[12010000]

  kkkk-dddd-llll=0000-0001-0001 lock=0 pin=0 latch#=1

  lwt=0x52d9ea40[0x52d9ea40,0x52d9ea40] ltm=0x52d9ea48[0x52d9ea48,0x52d9ea48]

  pwt=0x52d9ea58[0x52d9ea58,0x52d9ea58] ptm=0x52d9eab0[0x52d9eab0,0x52d9eab0]

  ref=0x52d9ea30[0x52d9ea30, 0x52d9ea30] lnd=0x52d9eabc[0x52d9eabc,0x52d9eabc]

    LIBRARY OBJECT: object=52d9e7b0

    type=CRSR flags=EXS[0001] pflags= [00] status=VALD load=0

    CHILDREN: size=16

    child#    table reference   handle

    ------ -------- --------- --------

         0 52d9e96c  52d9e6cc 52d9e4ac

         1 52d9e96c  52d9e70c 52d885cc

==>這就是我們前邊提到過的子指標,每個都指向了一個不同的handle   

    DATA BLOCKS:

    data#     heap  pointer status pins change    alloc(K)  size(K)

    ----- -------- -------- ------ ---- ------     -------- --------

        0 52d9e9b8 52d9e838 I/-/A     0 NONE       0.86     1.09

==>此處的heap就是指記憶體地址.  

==>這裡存放的就是SQL程式碼及使用者連線資訊

    HEAP DUMP OF DATA BLOCK 0:

******************************************************

HEAP DUMP heap name="library cache"  desc=0x52d9e9b8

 extent sz=0x224 alt=32767 het=16 rec=9 flg=2 opc=0

 parent=0x5000002c owner=0x52d9e7b0 nex=(nil) xsz=0x224

EXTENT 0 addr=0x52d9e558

  Chunk 52d9e560 sz=      540    perm      "perm           "  alo=448

52D9E560 5000021D 00000000 52D9E7A0 000001C0  [...P.......R....]

52D9E570 52D9E704 52D9E660 00020002 52D9E57C  [...R`..R....|..R]

52D9E580 52D9E57C 00000000 52D9E588 52D9E588  [|..R.......R...R]

52D9E590 00000000 52D9E594 52D9E594 00000000  [.......R...R....]

52D9E5A0 52D9E5A0 52D9E5A0 00000000 52D9E5AC  [...R...R.......R]

52D9E5B0 52D9E5AC 00000000 52D9E5B8 52D9E5B8  [...R.......R...R]

…….

52D9E8D0 52D9E630 00000000 52D9E570 00000000  [0..R....p..R....]

52D9E8E0 00000000 00000000 00000000 00000000  [................]

52D9E8F0 00000000 00000000 00000002 0000000D  [................]

52D9E900 00000001 00000000                    [........]       

Permanent space    =      900

******************************************************

  BUCKET 4581 total object count=1

我們以handle:52d885cc為例看一下Library Cache Object的結構:

******************************************************

  LIBRARY OBJECT HANDLE: handle=52d885cc

  namespace=CRSR flags=RON/KGHP/PN0/[10010000]

  kkkk-dddd-llll=0000-0041-0041 lock=0 pin=0 latch#=1

  lwt=0x52d885e4[0x52d885e4,0x52d885e4] ltm=0x52d885ec[0x52d885ec,0x52d885ec]

  pwt=0x52d885fc[0x52d885fc,0x52d885fc] ptm=0x52d88654[0x52d88654,0x52d88654]

  ref=0x52d885d4[0x52d9e70c, 0x52d9e70c] lnd=0x52d88660[0x52d88660,0x52d88660]

    LIBRARY OBJECT: object=52d82a24

    type=CRSR flags=EXS[0001] pflags= [00] status=VALD load=0

    DEPENDENCIES: count=1 size=16

    dependency#    table reference   handle position flags

    ----------- -------- --------- -------- -------- -------------------

              0 52d82be0  52d82b20 52d82e58       14 DEP[01]

==>在dependency部分我們看到,這個cursor依賴的物件handle:  52d82e58

==>這個handle指向的就是EYGLE.EMP表,如果以上兩個CRSR訪問的是同一個物件,

==>那麼這兩個SQL才會是真的共享.這裡我們的sql雖然是相同的,訪問的卻是不同使用者

==>的資料表, 子指標的概念就出來了.

==>在這裡我們看到52d82e58指向的是EYGLE.EMP這個物件,也就是EYGLE所查詢的資料表.

    ACCESSES: count=1 size=16

    dependency# types

    ----------- -----

              0 0009

    TRANSLATIONS: count=1 size=16

    original    final

    -------- --------

    52d82e58 52d82e58

    DATA BLOCKS:

    data#     heap  pointer status pins change    alloc(K)  size(K)

    ----- -------- -------- ------ ---- ------     -------- --------

        0 52d8c244 52d827e4 I/-/A     0 NONE       1.09     1.64

        6 52d82ac0 52d817c4 I/-/A     0 NONE       3.70     3.73

==>這裡的Data Blocks是個重要的部分

==>每個控制塊包含一個heap descriptor,指向相應的heap memory,這個heap memory ==>包含的就是Diana Tree,P-Code,Source Code,Shared Cursor Context area等重要==>資料,也就是我們通常。所說的,解析過的SQL及執行計劃樹,真正到這裡以後,sql才得==>以共享.也就真正的避免了硬解析

    HEAP DUMP OF DATA BLOCK 0:

******************************************************   

HEAP DUMP heap name="library cache"  desc=0x52d8c244

 extent sz=0x224 alt=32767 het=16 rec=9 flg=2 opc=0

 parent=0x5000002c owner=0x52d82a24 nex=(nil) xsz=0x224

EXTENT 0 addr=0x52d80ff0

  Chunk 52d80ff8 sz=      464    free      "               "

52D80FF0                   C00001D1 00000000          [........]

52D81000 52D8C28C 52D8C28C 00000000 00000000  [...R...R........]

52D81010 00000000 00000000 00000000 00000000  [................]

        Repeat 26 times

52D811C0 00000000 00000000                    [........]       

  Chunk 52d811c8 sz=       76    freeable  "kgltbtab       "

52D811C0                   1000004D 52D80FF8          [M......R]

52D811D0 0A857928 52D82B68 00000000 00000000  [(y..h+.R........]

52D811E0 00000000 00000000 00000000 00000000  [................]

        Repeat 2 times

52D81210 00000000                             [....]           

EXTENT 1 addr=0x52d827cc

  Chunk 52d827d4 sz=      540    perm      "perm           "  alo=532

52D827D0          5000021D 00000000 52D82A14      [...P.....*.R]

52D827E0 00000214 00000000 0000001A 00000069  [............i...]

…………….

52D825D0 00000000 00000000 00000000 52D81ACF  [...............R]

52D825E0 00000000 00000000 00000000 00000000  [................]

        Repeat 3 times

52D82620 52D8263C 00000010 000006D4 00000010  [<&.R............]

52D82630 000006F4 00000010 000006F8 00000010  [................]

52D82640 000006FC 00000010 00000714 00000010  [................]

52D82650 00000720 00000010 0000072C 00000010  [ .......,.......]

52D82660 00000744 00000010 0000074C 00000010  [D.......L.......]

52D82670 00000764 00000010 0000077C           [d.......|...]   

Permanent space    =     3784

MARKS:

  Mark 0x52d8237c

******************************************************

這裡的handle=52d82e58就是sql依賴的物件資訊:

BUCKET 63037:

  LIBRARY OBJECT HANDLE: handle=52d82e58

  name=EYGLE.EMP

  hash=7310f63d timestamp=08-26-2004 10:23:40

  namespace=TABL/PRCD/TYPE flags=KGHP/TIM/SML/[02000000]

  kkkk-dddd-llll=0000-0501-0501 lock=0 pin=0 latch#=1

  lwt=0x52d82e70[0x52d82e70,0x52d82e70] ltm=0x52d82e78[0x52d82e78,0x52d82e78]

  pwt=0x52d82e88[0x52d82e88,0x52d82e88] ptm=0x52d82ee0[0x52d82ee0,0x52d82ee0]

  ref=0x52d82e60[0x52d82e60, 0x52d82e60] lnd=0x52d82eec[0x52d7dcf0,0x52d89fc8]

    LIBRARY OBJECT: object=52d81594

    type=TABL flags=EXS/LOC[0005] pflags= [00] status=VALD load=0

==>Type:物件型別,這裡是一張表   

==>flags:代表物件狀態

    DATA BLOCKS:

    data#     heap  pointer status pins change    alloc(K)  size(K)

    ----- -------- -------- ------ ---- ------     -------- --------

        0 52d8c1e4 52d8161c I/-/A     0 NONE       0.66     1.09

        8 52d81238 52d80a18 I/-/A     0 NONE       1.10     1.13

       10 52d8129c 52d80ea0 I/-/A     0 NONE       0.12     0.37

    HEAP DUMP OF DATA BLOCK 0:

******************************************************

HEAP DUMP heap name="library cache"  desc=0x52d8c1e4

 extent sz=0x224 alt=32767 het=16 rec=9 flg=2 opc=0

 parent=0x5000002c owner=0x52d81594 nex=(nil) xsz=0x224

==>每個heap descriptor 都包含一個owner部分,指向所有者,這裡的 52d81594 也就==>是EYGLE.EMP指向的Library物件:  LIBRARY OBJECT: object=52d81594

EXTENT 0 addr=0x52d81220

  Chunk 52d81228 sz=      540    perm      "perm           "  alo=196

52D81220                   5000021D 00000000          [...P....]

52D81230 52D81584 000000C4 5000002C 00000824  [...R....,..P$...]

52D81240 52D81594 52D80A00 52D80A08 00000000  [...R...R...R....]

52D81250 00000000 05010200 00000000 00000000  [................]

52D81260 534C474B 61656820 00000070 00000000  [KGLS heap.......]

52D81270 00107FFF 7FFF7FFF 00000401 00000000  [................]

52D81280 52D81280 52D81280 52D8129C 00000000  [...R...R...R....]

52D81290 52D80EA0 00040000 52FF5C14 5000002C  [...R.....\.R,..P]

……..

52D80EE0 00000000 00000000 00000000 00000000  [................]

        Repeat 15 times

52D80FE0 00000000                             [....]           

Total heap size    =      340

FREE LISTS:

 Bucket 0 size=0

Total free space   =        0

UNPINNED RECREATABLE CHUNKS (lru first):

PERMANENT CHUNKS:

  Chunk 52d80e90 sz=      340    perm      "perm           "  alo=120

52D80E90 50000155 00000000 00000000 00000078  [U..P........x...]

52D80EA0 00000000 00000002 00000068 00000004  [........h.......]

52D80EB0 52D80EB0 52D80EB0 52D80EB8 52D80EB8  [...R...R...R...R]

52D80EC0 00000000 00000000 00000005 52D80ECC  [...............R]

52D80ED0 52D80ECC 52D80ED4 52D80ED4 00000000  [...R...R...R....]

52D80EE0 00000000 00000000 00000000 00000000  [................]

        Repeat 15 times

52D80FE0 00000000                             [....]           

Permanent space    =      340

******************************************************

  BUCKET 63037 total object count=1