Oracle 查詢真實執行計划


什么是真實執行計划

獲取Oracle的執行計划,有幾種方式。(本文使用Oracle 11g XE版本,以及普通用戶scott登錄)

  • explain plan for
    有兩個步驟:

    • explain plan for ${SQL}
    • select * from table(dbms_xplan.display);

    這一個方法可以在PLSQLDev的cmd窗口和sql窗口執行,同時不需要給用戶授權。
    示例:

  • autotrace
    有兩個步驟:

    • set autot on
    • 執行${SQL}

    但普通用戶需要授權,才能執行。不了解授權過程,知道的同學可以留言。
    並且在我的PLSQLDev里無法執行,必須得到SqlPlus才能執行。
    示例:

    可以看到多了一些統計信息,不過不是十分直觀。

但是,上面兩種方法

使用AUTOTRACE或者EXPLAIN PLAN FOR 獲取的執行計划來自於PLAN_TABLE。PLAN_TABLE是一個會話級的臨時表,里面的執行計划並不是SQL真實的執行計划,它只是優化器估算出來的。真實的執行計划不應該是估算的,應該是真正執行過的。SQL執行過的執行計划存在於共享池中,具體存在於數據字典V$SQL_PLAN中,帶有A-Time的執行計划來自於V$SQL_PLAN,是真實的執行計划,而通過AUTOTRACE、通過EXPLAIN PLAN FOR獲取的執行計划只是優化器估算獲得的執行計划。(注1)

這里說的帶有A-Time的執行計划,即是本文所說的真實執行計划。

  • 真實執行計划
    這種方法需要對普通用戶授權,可用以下語句一次性授權。
grant select any dictionary to scott;

這種執行計划結果如下:

可以看到多了A-Rows、A-Time等字段。

Starts 表示這個操作執行的次數
E-Rows表示優化器估算的行數,就是普通執行計划中的Rows
A-Rows表示真實的行數
A-Time表示累加的總時間。與普通執行計划不同的是,普通執行計划中的Time是假的,而A-Time是真實的。
Buffers表示累加的邏輯讀
Reads表示累加的物理讀
(注2)

Starts、A-Rows、A-Time這幾個字段很直觀,對於非數據庫開發人員來說,容易理解。
真實執行計划的獲取方式 ,下面會介紹。

需要注意的是,普通執行計划估算出來的行數,受直方圖統計信息的影響,可能會使優化器對執行計划的選擇產生誤判(例如本該走HASH JOIN,結果變成NESTED LOOPS)。因此,直方圖統計信息應該定期更新。這項工作在我司是DBA的日常工作。

如何獲取真實的執行計划

首先要有訪問動態性能視圖的權限,可用以下語句授權

grant select any dictionary to scott;

有了權限之后,分以下幾步走

1.alter session set statistics_level = all;
(這一步對當前會話窗口有效,可以不做,下面解釋)

2.執行語句;
(如果上一步不做,則需要在語句中添加 /*+ gather_plan_statistics /。 例如:select /+ gather_plan_statistics */ * from dual; 但這樣做比較麻煩 ,每條語句都要加上,不推薦)

3.找出執行語句的SQL ID,例如:
select v.last_active_time, v.* from v$sql v where v.last_active_time > to_date('2019/10/02 17:00:00', 'yyyy/mm/dd hh24:mi:ss') and v.sql_text like 'select * from %' and v.parsing_schema_name = 'SCOTT' order by v.last_active_time desc;

參數根據實際情況修改,越精確越好。
可以得到如下計划,把SQL ID取出

4.根據SQL ID查出執行計划

select * from table(dbms_xplan.display_cursor('b8x994z12hax9',null,'allstats last'));

其中第一個參數就是第3步獲得的SQL ID。可得到執行計划

復制出來貼到notepad++

可以看到已經有了實際執行的信息。
這個例子還比較簡單,可以試試下面這個例子。

select d.dname, d.loc, e.empno, e.ename
  from emp e, dept d
 where e.deptno = d.deptno
 order by d.dname, e.empno;

執行計划如下:

下面還有更多的信息,可以知道每一步操作的具體信息,比如兩個表之間通過什么關聯等。

總結

真實執行計划提供了SQL執行的真實信息,包括A-Time(真實時間)、A-Rows(真實行數)、Starts(步驟執行次數)等,對於非數據庫開發人員來說,十分直觀方便。我也借此在工作優化了10+ SQL,收獲滿滿~
在這里要推薦一本書《SQL 優化核心思想》,羅炳森 黃超 鍾僥 著。本文的所有文字引用,均摘自此書。我沒有完全看懂這本書,但目前在工作中,已經夠用了。


免責聲明!

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



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