v$sql和v$sqlarea的區別

llnnmc發表於2017-04-25

v$sql

共享池庫快取中在子指標級別上的SQL統計資訊,包含了所有使用者執行過的所有SQL資訊。不同使用者、不同會話執行相同的SQL的語義、執行計劃可能會不同,這些SQL的字面值相同,即具有相同的sql_id,透過不同的子指標編號child_number來區分。


v$sqlarea

共享池庫快取中在父指標級別上的SQL統計資訊。對於相同字面值的SQL語句僅以一行顯示,忽略了相同SQL語句在執行會話、語義、執行計劃上的不同,而版本計數version_count則反映了子指標的數量。


Oracle 10g以前,v$sqlv$sqlarea的定義都是來自於同一張底層表x$kglcursor,而該表的定義又來自於另一張底層表x$kglobv$sqlarea是在x$kglcursor表上對SQL字面值進行group by後的聚合。而從Oracle 10g開始,這兩個檢視來自於兩個不同的底層表,v$sql(gv$sql)來自於x$kglcursor_child,而v$sqlareagv$sqlarea)則來自於x$kglcursor_child_sqlid,v$sqlarea也不再包含group by子句,這使得以前版本中查詢v$sqlarea的效能問題得以緩解。並且,對於未執行的或者buffer_gets0SQL指標,從Oracle 10g開始在v$sql中被過濾掉不再列出。


以下用一個簡單實驗闡述其區別。


在使用者cmes中建立一張和scott使用者同樣的表emp

conn cmes/cmes

create table emp as select * from scott.emp;


重啟資料庫,清理一下共享池中的資訊

conn / as sysdba

startup force


cmes使用者執行一個查詢,透過autotrace觀察一下執行計劃和統計資訊

conn cmes/cmes

set autot on

select * from emp;


執行計劃

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

Plan hash value: 3956160932


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

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |      |    14 |  1218 |     3   (0)| 00:00:01 |

|   1 |  TABLE ACCESS FULL| EMP  |    14 |  1218 |     3   (0)| 00:00:01 |

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


Note

-----

   - 'PLAN_TABLE' is old version

   - dynamic sampling used for this statement (level=2)



統計資訊

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

         60  recursive calls

          0  db block gets

         49  consistent gets

          3  physical reads

          0  redo size

       1631  bytes sent via SQL*Net to client

        519  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          4  sorts (memory)

          0  sorts (disk)

         14  rows processed


這個查詢統計顯示,執行了3個磁碟物理讀,49個記憶體一致性讀。


查一下v$sql中記錄的資訊

col sql_text for a30

select sql_text, executions, optimizer_mode, optimizer_cost, disk_reads, buffer_gets, child_number, sql_id, address, hash_value from v$sql where sql_text='select * from emp';


SQL_TEXT                       EXECUTIONS OPTIMIZER_ OPTIMIZER_COST DISK_READS BUFFER_GETS CHILD_NUMBER SQL_ID        ADDRESS          HASH_VALUE

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

select * from emp                       1 ALL_ROWS                3          3          49            0 a2dk8bdn0ujx7 000007FF05FE38B0 1745700775


記錄的資訊和autotrace顯示的資訊完全一致,child_number是子指標的編號。


再執行一次這個查詢

select * from emp;


執行計劃

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

Plan hash value: 3956160932


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

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |      |    14 |  1218 |     3   (0)| 00:00:01 |

|   1 |  TABLE ACCESS FULL| EMP  |    14 |  1218 |     3   (0)| 00:00:01 |

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


Note

-----

   - 'PLAN_TABLE' is old version

   - dynamic sampling used for this statement (level=2)



統計資訊

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

          0  recursive calls

          0  db block gets

          4  consistent gets

          0  physical reads

          0  redo size

       1631  bytes sent via SQL*Net to client

        519  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

         14  rows processed


再查一下v$sql中記錄的資訊

col sql_text for a30

select sql_text, executions, optimizer_mode, optimizer_cost, disk_reads, buffer_gets, child_number, sql_id, address, hash_value from v$sql where sql_text='select * from emp';


SQL_TEXT                       EXECUTIONS OPTIMIZER_ OPTIMIZER_COST DISK_READS BUFFER_GETS CHILD_NUMBER SQL_ID        ADDRESS          HASH_VALUE

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

select * from emp                       2 ALL_ROWS                3          3          53            0 a2dk8bdn0ujx7 000007FF05FE38B0 1745700775


執行次數變為2次,磁碟物理讀未增加,因為資料已經在buffer中。記憶體讀繼續增加,和autotrace統計的情況一致。


看一下此時v$sqlarea中記錄的資訊

col sql_text for a30

select sql_text, executions, optimizer_mode, optimizer_cost, disk_reads, buffer_gets, version_count, sql_id, address, hash_value from v$sqlarea where sql_text='select * from emp';


SQL_TEXT                       EXECUTIONS OPTIMIZER_ OPTIMIZER_COST DISK_READS BUFFER_GETS VERSION_COUNT SQL_ID        ADDRESS          HASH_VALUE

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

select * from emp                       2 ALL_ROWS                3          3          53             1 a2dk8bdn0ujx7 000007FF05FE38B0 1745700775


內容與v$sql一致,子指標計數version_count1,即只有一個版本的相同SQL


現在用scott使用者執行同樣的查詢

conn scott/tiger

select * from emp;


查詢v$sql中的統計資訊

col sql_text for a30

select sql_text, executions, optimizer_mode, optimizer_cost, disk_reads, buffer_gets, child_number, sql_id, address, hash_value from v$sql where sql_text='select * from emp';


SQL_TEXT                       EXECUTIONS OPTIMIZER_ OPTIMIZER_COST DISK_READS BUFFER_GETS CHILD_NUMBER SQL_ID        ADDRESS          HASH_VALUE

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

select * from emp                       2 ALL_ROWS                3          3          53            0 a2dk8bdn0ujx7 000007FF05FE38B0 1745700775

select * from emp                       1 ALL_ROWS                4         13          87            1 a2dk8bdn0ujx7 000007FF05FE38B0 1745700775


現在列出了兩條相同字面值的SQL,子指標編號分別為01


查詢v$sqlarea中的統計資訊

col sql_text for a30

select sql_text, executions, optimizer_mode, optimizer_cost, disk_reads, buffer_gets, version_count, sql_id, address, hash_value from v$sqlarea where sql_text='select * from emp';


SQL_TEXT                       EXECUTIONS OPTIMIZER_ OPTIMIZER_COST DISK_READS BUFFER_GETS VERSION_COUNT SQL_ID        ADDRESS          HASH_VALUE

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

select * from emp                       3 ALL_ROWS                4         16         140             2 a2dk8bdn0ujx7 000007FF05FE38B0 1745700775


可以看到,相同字面值的SQL被合計為一條,版本計數version_count2,即存在兩個子指標。而執行次數、磁碟物理讀次數、記憶體讀次數便是它們的合計值,這就是v$sqlarea的聚合作用。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28974745/viewspace-2137954/,如需轉載,請註明出處,否則將追究法律責任。

相關文章