oracle sql資源消耗相關視圖

一、常用視圖說明

Oracle sql語句資源消耗監控,最常用的系統視圖有:

v$sql

v$sqlarea

v$sqltext

v$session

v$sql和v$sqlarea基本相同,記錄了共享SQL區(share pool)中SQL統計信息,如內存消耗、IO(物理磁盤讀和邏輯內存讀)、排序操作、哈希ID等數據。不同之處在於v$sql爲每一條SQL保留一個條目,而v$sqlarea中根據sql_text(需要注意,該處存儲的爲當前SQL指針的前1000個字符,也就是說這裏記錄的SQL可能是不完整的!)進行group by,統計列進行sum(),通過version_count計算子指針的個數。

  然而,文本(sql_text)相同的SQL語句在數據庫中意義可能完全不同。比如數據庫中存在兩個用戶User1和User2,這兩個用戶各擁有一張數據表EMP。那麼當兩個用戶發出查詢select count(*) from emp;時各自訪問自己SCHEMA中的表EMP,而兩者表內容不同所以其資源消耗肯定也不同。此時,在v$sql中會有這兩條完全一樣的SQL各自的統計信息,而在v$sqlarea中sql_text相同的2個指針會合並起來,執行次數、DISK_READS、BUFFER_GETS等統計信息都會累加(sum),version_count會顯示爲2,這就是v$sqlarea的聚合作用。

 

v$sqltext中沒有統計信息,然而卻存儲着完整的SQL語句及其哈希ID等。

對於這三者,我們可以使用視圖v$fixed_view_definition來查看視圖的源表,如下:

SELECT view_definition FROM v$fixed_view_definition WHERE view_name='GV$SQL';

SELECT view_definition FROM v$fixed_view_definition WHERE view_name='GV$SQLAREA';

SELECT view_definition FROM v$fixed_view_definition WHERE view_name='GV$SQLTEXT';

注:視圖名爲V$SQL但該視圖的源又是GV$SQL,所以直接使用GV$SQL,其他兩個也如此。

通過以上3條語句可以發現,V$SQL數據來源X$KGLCURSOR_CHILD,其實數據還是來源於X$KGLOB;而V$SQLAREA數據來源X$KGLCURSOR_CHILD_SQLID本質是對X$KGLCURSOR_CHILD按照sql_id等字段分組彙總後的結果;V$SQLTEXT數據來源X$KGLNA。

v$session主要用來確定會話相關信息,如通過SID和SERIAL#來唯一確定一個session(SID可能會重複)、會話擁有者用戶名USERNAME、會話狀態(active:正在執行SQL語句、inactive:等待操作、killed:被殺死)、會話由哪個客戶端發起(MACHINE、TERMINAL)、正在執行什麼SQL(通過SQL_ADDRESS、SQL_HASH_VALUE、SQL_ID、SQL_CHILD_NUMBER確定,有這些再借助v$sqltext就能知道)、甚至上一次執行的SQL是什麼(通過PREV_SQL_ADDRESS等確定)、鎖等待相關信息(如所在表、文件、塊、被鎖行)等。

 

高資源消耗SQL查找定位

1)查看讀硬盤多或佔用內存可能多的SQL:

select sql_text, disk_reads, buffer_gets, parsing_schema_name, executions

from v$sqlarea

order by disk_reads desc;

說明:單純從V$sqlarea中是無法查出每個SQL消耗的內存量的,但我們可以藉助磁盤讀次數間接反映可能的消耗內存量較大的SQL語句,然後再借助執行計劃(如v$sql_plan視圖)具體查看。

利用系統視圖v$sqlarea,其中disk_reads是磁盤讀次數,也是主要字段,剩餘字段均爲參考字段。其中,buffer_gets是內存讀次數,parsing_schema_name是首次編譯者模式名(一般與user名相同),executions是語句執行次數。

需要注意的是,v$sqlarea中sql_text可能不完整,若需要完整的則需要藉助hash_value或sql_id結合v$sqltext來查看分析。

2)查看執行次數多的SQL

select sql_text, executions, parsing_schema_name

from v$sqlarea

order by executions desc;

3)查看排序多的SQL

select sql_text, sorts, parsing_schema_name

from v$sqlarea

order by sorts desc;

該處還應涉及Library Cache命中率、內存命中率等內容,暫不總結。

4)查看總消耗時間最多的前10條SQL語句
select *
from (select v.sql_id,
v.child_number,
v.sql_text,
v.elapsed_time,
v.cpu_time,
v.disk_reads,
rank() over(order by v.elapsed_time desc) elapsed_rank
from v$sql v) a
where elapsed_rank <= 10;

5)查看CPU消耗時間最多的前10條SQL語句
select *
from (select v.sql_id,
v.child_number,
v.sql_text,
v.elapsed_time,
v.cpu_time,
v.disk_reads,
rank() over(order by v.cpu_time desc) elapsed_rank
from v$sql v) a
where elapsed_rank <= 10;

6)查看消耗磁盤讀取最多的前10條SQL語句
select *
from (select v.sql_id,
v.child_number,
v.sql_text,
v.elapsed_time,
v.cpu_time,
v.disk_reads,
rank() over(order by v.disk_reads desc) elapsed_rank
from v$sql v) a
where elapsed_rank <= 10;

注:如查執行上面的查尋提示 RA-00942: table or view does not exist

出現這個體會提示並不是說數據庫實例中沒有 v$sql 對象,而是你當前的用戶沒有權限。解決辦法就是給當前用戶賦予 v$sqlarea 的查詢權限

sql>grant select any dictionary to myuser;

wKioL1mJgPzyH_arAABn5WFYJxI467.jpg-wh_50

相關視圖重要字段

v$sqlarea

v$sqlareav$sql和v$sqlarea基本類似,而v$sqlarea更常用,故僅對v$sqlarea常用字段進行說明,如下(個人參考Oracle官方文檔翻譯的,因是最新版本,所以會跟網絡上的有些出入):

SQL_TEXT:SQL語句的前1000個字符;

SQL_FULLTEXT:SQL語句的所有字符;

SQL_ID:緩存在高速緩衝區(library cache)中的SQL父遊標的唯一標識ID(注,類似於hash_value,不過hash_value是4bytes而sql_id是8bytes,sql_id更精確後期可能會替代hash_value);

SHARABLE_MEM:SQL語句及其子游標占用的共享內存大小;

PERSISTENT_MEM:打開SQL語句的生命週期內所佔用的固定內存大小(包含子游標);

RUNTIME_MEM:遊標執行期間所佔用的固定內存大小;

SORTS:語句執行導致的排序次數;

VERSION_COUNT:在緩存中以該語句爲父語句的子游標總數;

LOADED_VERSIONS:緩存中載入了這條語句上下文堆(KGL heap 6)的子游標數;

OPEN_VERSIONS:父遊標下打開的子游標個數;

USERS_OPENING:打開子游標的用戶個數;

FETCHES:SQL語句的fetch數;

EXECUTIONS:包含所有子游標在內該SQL語句共執行次數;

USERS_EXECUTING:執行過該語句所有子游標的用戶總數;

LOADS:語句被載入的總次數;

FIRST_LOAD_TIME:父遊標被首次載入(編譯)的時間;

PARSE_CALLS:父遊標下所有子游標解析調用次數;

DISK_READS:該語句通過所有子游標導致的讀磁盤次數;

DIRECT_WRITES:該語句通過所有子游標導致的直接寫入次數;

BUFFER_GETS:該語句通過所有子游標導致的讀緩存次數;

APPLICATION_WAIT_TIME:應用等待時間;

USER_IO_WAIT_TIME:用戶I/O等待時間;

PLSQL_EXEC_TIME:PLSQL執行時間;

ROWS_PROCESSED:該SQL語句處理的總行數;

OPTIMIZER_COST:此查詢優化給出的成本數;

PARSING_USER_ID:第一次解析該父語句的用戶ID;

PARSING_SCHEMA_ID:第一次解析該語句SCHEMA的ID;

PARSING_SCHEMA_NAME:解析該語句的SCHEMA的NAME;

KEPT_VERSIONS:指出是否當前子游標被使用DBMS_SHARED_POOL包標記爲常駐內存;

ADDRESS:當前遊標父句柄(唯一指向該遊標的一種地址編號);

HASH_VALUE:該語句在library cache中hash值;

PLAN_HASH_VALUE:執行計劃的hash值,可依此確定兩個執行計劃是否相同(取代每行每字符進行比較的方式);

CPU_TIME:該語句解析、執行和fetch(取值)所消耗的CPU時間;

ELAPSED_TIME:該語句解析、執行和fetch(取值)所經過的時間;

LAST_ACTIVE_TIME:查詢計劃最後一次執行的時間;

LOCKED_TOTAL:所有子游標被鎖的次數;

v$sqltext

ADDRESS:當前遊標父句柄(唯一指向該遊標的一種地址編號);

HASH_VALUE:該遊標(子游標)在library cache中唯一hash值;

SQL_ID:緩存遊標中該SQL的一個唯一標識值;

COMMAND_TYPE:SQL語句類型,如select、insert、update等;

PIECE:排序SQL文本的碎片數;

SQL_TEXT:包含一個完整SQL中的某一小塊SQL文本字符(要完整的SQL語句需要把這些碎片組合起來);

v$session

SADDR:session地址;

SID:session標識值,常跟serial#聯合唯一確定一個session(在殺進程時,有時SID會重用,造成誤殺。而serial會增加但不會重複,sid 在同一個instance的當前session中是一個unique key,而sid ,serial#則是在整個instance生命期內的所有session中是unique key);

SERIAL#:會話序列號,用於在一個會話結束而另一個會話重用這該會話的SID時,唯一確定一個會話;

AUDSID:審計會話ID,可以通過audsid查詢當前session的sid,select sid from v$session where audsid=userenv('sessionid');

PADDR:進程地址,關聯v$process的addr字段,通過這個可以查詢到進程對應的session;

USER#:同於dba_users中的user_id,Oracle內部進程user#爲0;

USERNAME:會話擁有者用戶名,等於dba_users中的username,Oracle內部進程的username爲空;

COMMAND:正在執行的SQL語句類型,如1爲create table、3爲select等;

OWNERID:如果該列值爲2147483644則值無效,否則值用於會話遷移、並行等;

TADDR:Address of transaction state object;

LOCKWAIT:標識當前查詢是否處於鎖等待狀態,爲空則表示無等待;

STATUS:標識session狀態,Active正執行SQL語句,inactive等待操作,killed被標註爲殺死;

SERVER:服務器類型,DEDICATED專用、SHARED共享等;

SCHEMA#:SCHEMA標識ID值,Oracle內部進程的schema#爲0;

SCHEMANAME:SCHEMA用戶名,Oracle內部進程的爲sys;

OSUSER:客戶端操作系統用戶名;

PROCESS:客戶端操作系統進程ID;

MACHINE:操作系統機器名;

TERMINAL:操作系統終端名;

PROGRAM:操作系統應用程序名,如EXE或sqlplus.exe;

TYPE:會話類型,如BACKGROUND或USER;

SQL_ADDRESS:和SQL_HASH_VALUE一起使用標識正在執行的SQL語句;

SQL_HASH_VALUE:和SQL_ADDRESS一起使用標識正在執行的SQL語句;

SQL_ID:正在執行的SQL語句的標識ID;

SQL_CHILD_NUMBER:正在執行的SQL語句的子ID;

FIXED_TABLE_SEQUENCE:當session完成一個user call後就會增加的一個數值,也就是說,如果session掛起,它就不會增加。因此可以根據這個字段來監控某個時間點以來的session性能情況。例如,一個小時前某個session的此字段數值爲10000,而現在是20000,則表明一個小時內其user call較頻繁,可以重點關注此session的performance statistics。

ROW_WAIT_OBJ#:被鎖定行所在table的object_id,和dba_object中的object_id關聯可以得到被鎖定的table name;

ROW_WAIT_FILE#:被鎖定行所在的datafile id,和v$datafile中的file#關聯可以得到datafile name;

ROW_WAIT_BLOCK#:被鎖定的塊ID;

ROW_WAIT_ROW#:被鎖定的當前行;

LOGON_TIME:登錄時間;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章