1. 程式人生 > >Oracle 查詢真實執行計劃

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 優化核心思想》,羅炳森 黃超 鍾僥 著。本文的所有文字引用,均摘自此書。我沒有完全看懂這本書,但目前在工作中,已經夠用了