【Oracle】獲取SQL執行計划


一、plsql developer工具F5
        在sqldeveloper中選中sql按F5即可查看執行計划
        
二、explain plan for 
        在sql plus中執行 explain plan for SQL語句,然后執行sql獲取執行計划   
    Select * from table(DBMS_XPLAN.display('PLAN_TABLE'));
        
        
        這種方式和直接按F5 結果是一樣的。
        優點:不用執行sql即可獲取執行計划,方便
        缺點:沒辦法看執行了多少次邏輯讀,多少次物理讀,表訪問了多少次,處理了多少行。
三、set autotrace on
        在sql plus中執行命令,set autotrace on 開啟trace,然后執行sql,完成之后會出結果
        
        
        注: Set autotrace on:得到執行計划,輸出運行結果
              Set autotrace traceonly :得到執行計划,不輸出運行結果
              Set autotrace traceonly explain :得到執行計划,不輸出運行結果和統計信息部分,僅展現執行計划部分
              Set autotrace traceonly statistics :不輸出運行結果和執行計划部分,僅展現統計信息部分
              該命令不能在plsql developer中使用,得在 sql*plus中使用
        優點:可以看到執行過程的統計信息(執行了多少次邏輯讀,多少次物理讀等信息)
                  可以看到執行了處理了多少行 
        缺點:必須等sql運行結束  
                  沒辦法看到表被訪問了多少次 
四、statistics_level=all
        1.執行語句,設置statistics_level
alter session set statistics_level=all;
        2.運行sql,查找對應的SQL_ID
        運行sql時可以加一些注釋,方便查找
        
select * from v$sqlarea where sql_text like '%sunlingchao%';
        3.執行以下SQL獲取執行計划
select * from table(dbms_xplan.display_cursor('&sql_id',null,'allstats last'));
        或者
        1.在執行SQL的時候加上hint
/*+ gather_plan_statistics */
       2.執行上面第3步獲取執行計划
 
        關鍵字解讀:
        Starts:該sql執行的次數。
        E-Rows:執行計划預估的行數。
        A-Rows:實際返回的行數。A-Rows跟E-Rows做比較,可以確定哪一步執行計划出問題。
        A-Time:每一步實際執行的時間(HH:MM:SS.FF),根據這一行可以知道該sql耗時在了哪個地方。
        Buffers:每一步實際執行的邏輯讀或一致性讀。
        Reads:物理讀。
        OMem:當前操作完成所有內存工作區(Work Aera)操作所總共使用私有內存(PGA)中工作區的大小,這個數據是由優化器統計數據以及前一次執行的性能數據估算得出的
        1Mem:當工作區大小無法滿足操作所需的大小時,需要將部分數據寫入臨時磁盤空間中(如果僅需要寫入一次就可以完成操作,就稱一次通過,One-Pass;否則為多次通過,Multi_Pass).該列數據為語句最后一次執行中,單次寫磁盤所需要的內存大小,這個由優化器統計數據以及前一次執行的性能數據估算得出的
        User-Mem:語句最后一次執行中,當前操作所使用的內存工作區大小,括號里面為(發生磁盤交換的次數,1次即為One-Pass,大於1次則為Multi_Pass,如果沒有使用磁盤,則顯示OPTIMAL)
        OMem、1Mem為執行所需的內存評估值,0Mem為最優執行模式所需內存的評估值,1Mem為one-pass模式所需內存的評估值。0/1/M 為最優/one-pass/multipass執行的次數。Used-Mem耗的內存。
        
        優點:可以清晰看出來表被訪問多少次;有詳細的E-Rows和A-Rows中得到預測的行數和真實的行數;從Buffers中看真實的邏輯讀
        缺點:必須等到sql執行結束;必須將查詢結果輸出,遇到數據量大的時候很麻煩;看不出遞歸調用的次數,看不出物理讀的多少(不過邏輯讀才是重點)
五、dbms_xplan.display_cursor('&sql_id')
        1.獲取到sql_id
        2.執行查詢SQL
select * from table(dbms_xplan.display_cursor('&sqlId'));
        
        優點:不用執行SQL,只需要知道SQL_ID;真實的執行計划;
        缺點:沒有相關統計信息;沒辦法看到表被訪問多少次;沒辦法看到處理多少行
六、10046 trace跟蹤
        1.開啟10046 trace
alter session set events '10046 trace name context forever,level 12';
        2.執行SQL
        3.關閉10046 trace
alter session set events '10046 trace name context off';
        4.查找trace文件路徑,獲取trace文件
        優點:可以看到SQL對應的等待時間;可以看出執行的統計信息;可以看到解析時間和執行時間;可以看到函數里面調用的sql的執行計划
        缺點:需要登陸數據庫服務器,獲取並格式化trace文件;沒辦法看到表被訪問多少次;
七、awrsqlrpt.sql
        1.@?/rdbms/admin/awrsqrpt.sql
        2.選擇你要的斷點(begin snap 和end snap)
        3.輸入sql_id
        或者
        執行SQL
SELECT output
  FROM TABLE(dbms_workload_repository.awr_sql_report_html(l_dbid     => 1045358809,
                                                          l_inst_num => 1,
                                                          l_bid      => 4457,
                                                          l_eid      => 4463,
                                                          l_sqlid    => 'cgc37m709dvm4'));

八、sql_monitor

  sql_monitor是oracle數據庫11g引進的特性,通過sqlmonitor可以在sql運行中看他們的實際執行計划。

SELECT m.sql_text,
       dbms_sqltune.report_sql_monitor(sql_id       => m.sql_id,
                                       TYPE         => 'HTML',
                                       report_level => 'ALL') AS report
  FROM gv$sql_monitor m
 WHERE 1 = 1
      /*and  m.sid = 2015
      AND m.session_serial# = 30119*/
   AND (m.sid, m.session_serial#) IN
       (SELECT s.sid,
               s.serial#
          FROM fnd_concurrent_requests fcr,
               gv$session              s
         WHERE fcr.request_id = 126796916
           AND fcr.oracle_session_id = s.audsid)
 ORDER BY 1;
 
總結:

1.如果某SQL執行非常長時間才會出結果,甚至慢到返回不了結果,這時候看執行計划就只能用方法1和     方法2;

2.跟蹤某條SQL最簡單的方法是方法1、2,其次就是方法3;

3.如果想觀察到某條SQL有多條執行計划的情況,只能用方法5和方法7;

4.如果SQL中含有多函數,函數中套有SQL等多層遞歸調用,想准確分析,只能使用方法6;

5.要想確保看到真實的執行計划,不能用方法1和方法2、3;

6.要想獲取表被訪問的次數,只能使用方法4;
 
補充說明: v$sql和v$sqlarea
v$sqlarea和v$sql兩個視圖的不同之處在於,v$sql中為每一條SQL保留一個條目,而v$sqlarea中根據sql_text進行group by,通過version_count計算子指針的個數。
v$sql視圖列舉了共享SQL區(Shared SQL Area)中的SQL統計信息,這個視圖中的信息未經分組,每個SQL指針都包含一條獨立的記錄
字段:
Column
Datatype
Descrption
SQL_TEXT VARCHAR2(1000) 當前SQL指針的前1000個字符(也就是說這里記錄的SQL是不完整的)
EXECUTIONS NUMBER 執行次數
DISK_READS NUMBER 這個子指針Disk Read的次數
BUFFER_GETS NUMBER 這個子指針的Buffer Gets數量
OPTIMIZER_MODE VARCHAR2(10) SQL執行的優化器模式
OPTIMIZER_COST NUMBER SQL執行成本
HASH_VALUE NUMBER 在Library Cache中父指針的Hash Value值
SQL第一次執行時,SQL的HASH_VALUE被計算出來,並且隨之,這個SQL的父指針(Parent Cursor)在內存中被創建,一個子指針同時創建。父指針可以被認為是Hash Value的相關信息,子指針可以被認為是SQL的元數據。
再次執行這個查詢,統計信息中的物理讀(DISK_READS)不再增加,因為數據已經在Buffer中存在,而BUFFER_GETS繼續增加。執行次數也變為2次:
v$sqlarea列出了共享SQL區(Shared SQL Area)中的SQL統計信息,這些SQL按照SQL文本的不同,每條會記錄一行統計數據
Column
Datatype
Description
SQL_TEXT VARCHAR2(1000) 當前指針的前1000個字符
VERSION_COUNT NUMBER Cache中這個父指針下存在的子指針的數量
EXECUTIONS NUMBER 總的執行次數,包含所有子指針執行次數的匯總
DISK_READS NUMBER 所有子指針的Disk Reads總和
BUFFER_GETS NUMBER 所有子指針的Buffer Gets總和
OPTIMIZER_MODE VARCHAR2(10) SQL執行的優化器模
HASH_VALUE NUMBER 父指針的Hash Value

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM