Oracle執行計劃2(Explain Plan)

1、獲取執行計劃的方法

(1) explain plan for

步驟:javascript

  • 1:explain plan for 你的SQL;
  • 2:select * from table (dbms_xplan. display()) ;
  • 優勢:不須要真的執行,快捷方便
  • 缺點:沒有輸出運行時的統計信息(邏輯讀、遞歸調用,物理讀),由於沒有真正執行,因此不能看到執行了多少行、表被訪問了多少次等等

(2) set autotrace on

sqlplus登陸:php

用戶名/密碼@主機名稱:1521/數據庫名

步驟:css

  • 1:set sutoatrace on
  • 2:在這次執行你的sql;
  • 優勢:能夠看到運行時的統計信息(邏輯讀、遞歸調用,物理讀)
  • 缺點:不能看到表被訪問了多少次,也須要等sql執行完成才能看

(3) statistics_level=all

步驟:java

  • 1:alter session set statistics_level=all;
  • 2:在此處執行你的SQL;
  • 3:select * from table(dbms_xplan.display_cursor(null , null,'allstats last'));

假如使用了Hint語法: /*+ gather_plan_statistics */,就能夠省略步驟1,直接執行步驟2和3,獲取執行計劃python

關鍵字解讀:sql

  • Starts:該SQL執行的次數
  • E-Rows:爲執行計劃預計的行數
  • A-Rows:實際返回的行數,E-Rows和A-Rows做比較,就能夠看出具體那一步執行計劃出問題了
  • A-Time:每一步實際執行的時間,能夠看出耗時的SQL
  • Buffers:每一步實際執行的邏輯讀或一致性讀
  • Reads:物理讀
  • OMem:當前操做完成全部內存工做區操做總使用私有內存工做區(PGA)的大小
  • lMem:當工做區大小沒法符知足操做需求的大小時,須要將部分數據寫入臨時磁盤空間中(若是僅須要寫入一次就能夠完成操做,就稱一次經過,One-Pass;不然爲屢次經過,Multi-Pass)。改數據爲語句最後一次執行中,單次寫磁盤所須要的內存大小,這個是由優化器統計數據以及前一次執行的性能數據估算得出的
  • Used-Mem:語句最後一次執行中,當前操做所使用的內存工做區大小,括號裏面爲(發生磁盤交換的次數,1次即爲One-Pass,大於一次則爲Mullti-Pass,若是沒有使用磁盤,則顯示爲OPTI1MAL)
    OMem、lMem爲執行所須要的內存評估值,OMem爲最優執行模式所須要內存的評估值,Used-Mem爲消耗的內存

優勢:數據庫

  • 能夠從STARTS得出表被訪問多少次;
  • 能夠清晰地從E-ROWS和A-ROWS中分別得出預測的行數和真實的行數
    缺點:
  • 必須等到語句真正執行完成後,才能夠得出結果
  • 沒法控制記錄打屏輸出,不想aututrace有traceonly命令
  • 沒有專門的輸出統計信息,看不到遞歸調用的次數,看不出物理讀具體數值,不過有邏輯讀,邏輯讀纔是重點

(4) dbms_xplan.display_cursor獲取

步驟
從共享池獲取bash

//${SQL_ID}參數能夠從共享池拿 select * from table(dbms_xplan.display_cursor(${SQL_ID})); 

還能夠從AWR性能視圖裏獲取session

select * from table(dbms_xplan.display_awr(${SQL_ID})); 

多個執行計劃的狀況,能夠用相似方法查出函數

select * from table(dbms_xplan.display_cursor(${SQL_ID},0)); select * from table(dbms_xplan.display_cursor(${SQL_ID},1)); 

優勢:

  • 和explain同樣不須要真正執行,知道sql_id就好

缺點:

  • 不能判斷處理了多少行
  • 沒法判斷表被訪問了多少次
  • 沒有輸出運行時的相關統計信息(邏輯讀、遞歸調用、物理讀)

(5) 事件10046 trace跟蹤

步驟:

1:alter session set events '10046 trace name context forever,level 12';//開啓跟蹤 2:執行你的語句 3:alter session set events '10046 trace name context off';//關閉跟蹤 4:找到跟蹤產生的文件 5:tkprof trc文件 目標文件 sys=no sort=prsela,exeela,fchela(格式化命令) 

優勢:

  • 能夠看出SQL語句對應的等待事件
  • 能夠列出sql語句中的函數調用的
  • 能夠看出解析事件和執行事件
  • 能夠跟蹤整個程序包
  • 能夠看出處理的行數,產生的邏輯讀
    缺點:
  • 步驟比較繁瑣
  • 沒法判斷表被訪問了多少次
  • 執行計劃中的謂詞部分不能清晰地顯示出來

(6) awrsqrpt.sql

步驟:

1:@?/rdbms/admin/awrsqrpt.sql 具體能夠參考我以前的博客:https://smilenicky.blog.csdn.net/article/details/89429989 

2、解釋經典執行計劃的方法

能夠分爲兩種類型:單獨型和聯合型

聯合型分爲:關聯的聯合型和非關聯的聯合型

【單獨型】

單獨型比較好理解,執行順序是按照id=1,id=2,id=3執行,由遠及近
先scott登陸,而後執行sql,例子來自《收穫,不止SQL優化》一書

select deptno, count(*)
  from emp where job = 'CLERK' and sal < 3000 group by deptno 
 
在這裏插入圖片描述

因此能夠給出單獨型的圖例:


 
在這裏插入圖片描述

【聯合型關聯型】

(1) 聯合型的關聯型(NL)

這裏使用Hint的nl

select /*+ ordered use_nl(dept) index(dept) */ * from emp, dept where emp.deptno = dept.deptno and emp.comm is null and dept.dname != 'SALES' 

這圖來自《收穫,不止SQL優化》,能夠看出id爲2的A-Rows實踐返回行數爲10,id爲3的Starts爲10,說明驅動表emp訪問的結果集返回多少條記錄,被驅動表就被訪問多少次,這是關聯型的顯著特徵

 
在這裏插入圖片描述

 
在這裏插入圖片描述

 

 

 
在這裏插入圖片描述

關聯型不必定是驅動表返回多少條,被驅動表就被訪問多少次的,注意FILTER模式也是關聯型的

 

(2) 聯合型的關聯型(FILTER)

前面已經介紹了聯合型關聯型(nl)這種方法的,這種方法是驅動表返回多少條記錄,被驅動表就被訪問了多少次,不過這種狀況對於FILTER模式下並不適用

執行SQL,這裏使用Hint /*+ no_unnset */

select * from emp where not exists (select /*+ no_unnset */ 0 from dept where dept.dname='SALES' and dept.deptno = emp.deptno) and not exists(select /*+ no_unnset */ 0 from bonus where bonus.ename = emp.ename) 

ps:圖來自《收穫,不止SQL優化》一書,這裏能夠看出id爲2的地方,A-Rows實際返回行數爲8,而id爲3的地方,Starts爲3,說明對應SQL執行3次,也即dept被驅動表被訪問了3次,這和剛纔介紹的nl方式不一樣,爲何不一樣?


 
在這裏插入圖片描述

查詢一下SQL,能夠看出實際返回3條,其它的都是重複多的,

select dname, count(*) from emp, dept where emp.deptno = dept.deptno group by dname; 

因此,就很明顯了,被過濾了重複數據,也就是說FILTER模式的對數據進行過濾,驅動表執行結果集返回多少行不重複數據,被驅動表就被訪問多少次,FILTER模式能夠說是對nl模式的改善

(3) 聯合型的關聯型(UPDATE)

update emp e1 set sal = (select avg(sal) from emp e2 where e2.deptno = e1.deptno),comm = (select avg(comm) from emp e3) 

聯合型的關聯型(UPDATE)和FILTER模式相似,因此就不重複介紹

(4) 聯合型的關聯型(CONNECT BY WITH FILTERING)

select /*+ connect_by_filtering */ level, ename ,prior ename as manager from emp start with mgr is null connect by prior empno = mgr 

給出聯合型關聯型圖例:


 
在這裏插入圖片描述

【聯合型非關聯型】

能夠執行SQL

select ename from emp union all select dname from dept union all select '%' from dual 

對於plsql可使用工具查看執行計劃,sqlplus客戶端的可使用statistics_level=all的方法獲取執行計劃,具體步驟

  • 1:alter session set statistics_level=all;
  • 2:在此處執行你的SQL;
  • 3:select * from table(dbms_xplan.display_cursor(null , null,'allstats last'));
 
在這裏插入圖片描述

能夠給出聯合型非關聯型的圖例:


 
在這裏插入圖片描述
做者:smileNicky 連接:https://www.jianshu.com/p/bfb62aceebd7 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
相關文章
相關標籤/搜索