ORACLE資料庫SQL優化--->如何得到真實的執行計劃
在ORACLE資料庫裡通常可以使用如下的四種方法來得到目標SQL的執行計劃:
1,EXPLAIN PLAN命令
2,DBMS_XPLAN包
3,SQLPLUS中的AUTOTRACE開關
4,10046事件
除了第四種方法外,其他的三種方法得到的執行計劃都有可能不準確。在ORACLE資料庫中判斷得到的執行計劃是否準確,就是看目標SQL是否被真正的執行,真正執行過的SQL所對應的執行計劃就是準確的,反之,則有可能不準確。
對於使用第二種方法(DBMS_XPLAN)而言,針對不同的應用場景,你可以選擇如下四種方式的一種。
a, select * from table(dbms_xplan.display)
例如:
SQL> explain plan for select * from hr.employees;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1445457117
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 107 | 7276 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| EMPLOYEES | 107 | 7276 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------
8 rows selected.
b,select * from table(dbms_xplan.display_cursor(null,null,'advanced'));
c,select * from table(dbms_xplan.display_cursor('sql_id/hash_value',child_cursor_number,'advanced'));
d,select * from table(dbms_xplan.display_awr('sql_id'));
Note:執行select * from table(dbms_xplan.display)所得到的執行計劃可能是不準確的,因為它只是用於檢視使用explain plan命令得到的目標SQL的執行計劃,目標SQL此時還沒有真正執行,所以用它得到的執行計劃可能不正確。使用剩下的三種方式得到的執行計劃都是準確的,因為此時的目標SQL都已經被實際執行過了。
對第三種方法(即使用SQLPLUS中的AUTOTRACE)而言,可以有下面幾種方法來開啟:
set autotrace on;(目標SQL都已經被執行)
set autotrace traceonly;(目標SQL都已經被執行)
set autotrace traceonly explain; (對於查詢目標SQL時,是沒有被實際執行,但是如果目標SQL是DML語句時,這個時候DML是實際上已經被執行了)
由於SET AUTOTRACE命令後顯示的執行計劃實際上是來源於呼叫EXPLIAN PLAN命令,而用EXPLAIN PLAN命令得到的執行計劃有可能不準確(特別是在使用了繫結變數的情況下),所以使用SET AUTOTRACE命令所顯示的執行計劃也有可能不準確。
看一個如下的例子來驗證下使用explain plan和set autotrace命令後得到的執行計劃並不是目標SQL真實執行計劃:
SQL> show user
USER is "HR"
SQL> create table T1 as select * from dba_objects;
Table created.
SQL> insert into t1 select * from t1;
50319 rows created.
SQL> commit;
Commit complete.
SQL> insert into t1 select * from t1;
100638 rows created.
SQL> commit;
Commit complete.
SQL> select count(*) from t1;
COUNT(*)
----------
201276
在表T1的OBJECT_ID列上建立一個單鍵值的B樹索引IDX_T1
SQL> create index idx_t1 on t1(object_id);
Index created.
對T1表收集一下統計資訊:
SQL> exec dbms_stats.gather_table_stats(ownname=>'HR',tabname=>'T1',estimate_percent=>100,cascade=>true);
PL/SQL procedure successfully completed.
建立2個繫結變數X和Y,X=0,Y=100000
SQL> var x number;
SQL> var y number;
SQL> exec :x :=0
PL/SQL procedure successfully completed.
SQL> exec :y :=100000
PL/SQL procedure successfully completed.
檢視如下語句的執行計劃:
SQL> explain plan for select count(*) from t1 where object_id between :x and :y;
Explained.
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2351893609
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | FILTER | | | | | |
|* 3 | INDEX RANGE SCAN| IDX_T1 | 503 | 2515 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(TO_NUMBER(:X)<=TO_NUMBER(:Y))
3 - access("OBJECT_ID">=TO_NUMBER(:X) AND "OBJECT_ID"<=TO_NUMBER(:Y))
16 rows selected.
從上面可以看出使用EXPLAIN PLAN得到的執行計劃顯示目標SQL走的是對索引IDX_T1的索引範圍掃描。
但是實際情況是否是這樣呢?我們實際執行下上面的語句:
SQL> select count(*) from t1 where object_id between :x and :y;
COUNT(*)
----------
201276
用DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ADVANCED')得到目標SQL的真實執行計劃如下所示:
SQL> select * from table(dbms_xplan.display_cursor(null,null,'advanced'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID 9dhu3xk2zu531, child number 0
-------------------------------------
select count(*) from t1 where object_id between :x and :y
Plan hash value: 1410530761
--------------------------------------------------------------------------------
-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-
| 0 | SELECT STATEMENT | | | | 106 (100)|
|
| 1 | SORT AGGREGATE | | 1 | 5 | |
|
|* 2 | FILTER | | | | |
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
|
|* 3 | INDEX FAST FULL SCAN| IDX_T1| 201K| 982K| 106 (7)| 00:00:02
|
--------------------------------------------------------------------------------
-
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
1 - SEL$1
3 - SEL$1 / [email protected]$1
Outline Data
-------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('10.2.0.1')
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
INDEX_FFS(@"SEL$1"
"T1"@"SEL$1" ("T1"."OBJECT_ID"))
END_OUTLINE_DATA
*/
Peeked Binds (identified by position):
--------------------------------------
1 - :X (NUMBER): 0
2 - :Y (NUMBER): 100000
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(:X<=:Y)
3 - filter(("OBJECT_ID">=:X AND "OBJECT_ID"<=:Y))
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - (#keys=0) COUNT(*)[22]
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
51 rows selected.
從上面的執行計劃可以看出,現在目標SQL實際的執行計劃是走對索引IDX_T1的索引快速全掃描,這才是目標SQL的真實的執行計劃,即剛才用EXLPAIN PLAN命令得到的計劃是不準確的。
我們再來看下,使用SET AUTOTRACE 命令的情況。開啟當前SESSION的AUTOTRACE:
SQL> set autotrace traceonly
SQL> select count(*) from t1 where object_id between :x and :y;
Execution Plan
----------------------------------------------------------
Plan hash value: 2351893609
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | FILTER | | | | | |
|* 3 | INDEX RANGE SCAN| IDX_T1
| 503 | 2515 | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(TO_NUMBER(:X)<=TO_NUMBER(:Y))
3 - access("OBJECT_ID">=TO_NUMBER(:X) AND "OBJECT_ID"<=TO_NUMBER(:Y))
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
451 consistent gets
0 physical reads
0 redo size
413 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
從上面可以看出使用SET AUTOTRACE TRACEONLY後得到的執行計劃和之前用EXPLAIN PLAN命令得到的執行計劃是一樣的。即此時的SET AUTOTRACE TRACEONLY所得到的執行計劃是不準確的。
結論:通過上面的實驗可以證明使用了SET AUTOTRACE命令後顯示的執行計劃實際上是來源於呼叫EXPLAIN PLAN命令,而EXPLAIN PLAN命令所得到的執行計劃可能是不準確的(特別是在繫結變數的時候),索引使用SET AUTORACE命令的所顯示的執行計劃可能是不準確的。
ORACLE資料庫還有如下方法得到真實的執行計劃:
如果是ORACLE 10G及其以上的版本,該SQL的執行計劃又已經被ORACLE捕獲並存儲到了REPOSITORY中,在可以使用AWR SQL報告來得到真實的歷史執行計劃。
相關推薦
ORACLE資料庫SQL優化--->如何得到真實的執行計劃
在ORACLE資料庫裡通常可以使用如下的四種方法來得到目標SQL的執行計劃: 1,EXPLAIN PLAN命令 2,DBMS_XPLAN包 3,SQLPLUS中的AUTOTRACE開關 4,10046事件 除了第四種方法外,其他的三種方法得到的執行計劃都有可能不準確。在OR
ORACLE資料庫SQL優化--->如何執行計劃的執行順序
建議安裝(10g即以上版本上)xplan package,XPALN包其實是對DBMS_XPLAN包的封裝,使用XPLAN包就可以很清晰的看到執行計劃的執行順序。 安裝很簡單:其中xplan.sql_.txt可以到如下的網站下載: [[email protec
Mysql SQL優化系列之——執行計劃連線方式淺釋
關係庫SQL調優中,雖然思路都是一樣的,具體方法和步驟也是大同小異,但細節卻不容忽視,尤其是執行計劃的具體細節的解讀中,各關係庫確實有區別,特別是mysql資料庫,與其他關係庫的差別更大些,下面,我們僅就SQL執行計劃中最常見的連線方式,做以下簡要介紹和說明。 system : a syst
ORACLE 資料庫 SQL 優化
出處: 1.資料庫訪問優化法則 要正確的優化SQL,我們需要快速定位能性的瓶頸點,也就是說快速找到我們SQL主要的開銷在哪裡?而大多數情況效能最慢的裝置會是瓶頸點,如下載時網路速度可能會是瓶頸點,本地複製檔案時硬碟可能會是瓶頸點,為什麼這些一般的工
崔華基於oracle的SQL優化讀書筆記(一)如何得到真實的執行計劃
hash mes getting binary oracl only 中文 fun roc ---恢復內容開始--- 得到目標SQL的執行計劃,大致有以下四種方式: 1.explain plan 命令 2.DBMS_XPLAN包 3.SQLPLUS中的autotrace開關
Oracle之SQL優化專題02-穩固SQL執行計劃的方法
首先構建一個簡單的測試用例來實際演示: create table emp as select * from scott.emp; create table dept as select * from scott.dept; create index idx_emp_empno on emp(empno);
Oracle之SQL優化專題01-檢視SQL執行計劃的方法
在我2014年總結的“SQL Tuning 基礎概述”中,其實已經介紹了一些檢視SQL執行計劃的方法,但是不夠系統和全面,所以本次SQL優化專題,就首先要系統的介紹一下檢視SQL執行計劃的方法。 本文示例SQL為: --set lines 1000 pages 1000 select a.emp
MySQL資料庫SQL優化第四篇:通過trace分析優化器如何選擇執行計劃
MySQL5.6提供了對SQL的跟蹤trace,通過trace檔案能夠進一步瞭解為什麼優化器選擇A執行計劃而不是選擇B執行計劃,幫助我們更好地理解優化器行為。 使用方式:首先開啟trace,設定格式為JSON,設定trace最大能夠使用的記憶體大小,避免解析過程中
Oracle效能優化-讀懂執行計劃
Oracle的執行計劃 得到執行計劃的方式 Autotrace例子
SQL和PL/SQL的效能優化之二--執行計劃管理
1、提示--它們僅是建議,優化器可以選擇忽略他們。事實上,優化器將盡可能地遵從優化提示,哪怕會導致空難性的效能影響。一般來說,只有當你用盡非直接方法(收集統計資訊,建立柱狀圖及設定配置引數等)之後,才可以考慮使用提示。 下面是一些更常見的提示:
ORACLE 查看有多個執行計劃的SQL語句
title esc 計劃 有時 pan 轉載 div 通過 ans 轉載自:http://www.cnblogs.com/kerrycode/p/5288030.html ORACLE 查看有多個執行計劃的SQL語句 在SQL優化過程,有時候需要查看哪些S
Oracle之一條SQL對應多個執行計劃
解析:同一個表名對應不同的使用者,對用不同的表結構,就會產生一條SQL產生多個執行計劃。等 分結論4(一條SQL對應多個執行計劃): 一. 關於獲取執行計劃的6種方法和各自區別大家在上一例子中已經大致明白了。 1. explain plan for獲取; 2. set autotrace o
檢視Oracle資料庫SQL執行歷史
方法1:使用LogMiner工具 優點:可以完全挖掘日誌內容,找出所有執行過的SQL語句 缺點: 如果沒有啟用歸檔日誌,則只能對聯機日誌進行挖掘 需要掌握LogMiner的用法 方法2:檢視HIST檢視 優點:簡單,只要使用普通的select語句查
宜信-運維-資料庫|SQL優化:一篇文章說清楚Oracle Hint的正確使用姿勢
一、提示(Hint)概述 1、為什麼引入Hint? Hint是Oracle資料庫中很有特色的一個功能,是很多DBA優化中經常採用的
Oracle 查詢真實執行計劃
什麼是真實執行計劃 獲取Oracle的執行計劃,有幾種方式。(本文使用Oracle 11g XE版本,以及普通使用者scott登入) explain plan for 有兩個步驟: explain plan for ${SQL} select * from table(dbms_xplan.display
轉://從一條巨慢SQL看基於Oracle的SQL優化
查看 針對性 map 分區 有關 需要 fix pts 大局觀 http://mp.weixin.qq.com/s/DkIPwbDKIjH2FMN13GkT4w 本次分享的內容是基於Oracle的SQL優化,以一條巨慢的SQL為例,從快速解讀SQL執行計劃、如何從執行計劃中
為什麼預估執行計劃與真實執行計劃會有差異?
雲和恩墨北區技術project師 專注於 SQL 稽核和優化相關工作。以前服務的客戶涉及金融保險、電信運營商、政府、生產製造等行業。 郭成日 本文由恩墨大講堂154期線上分享整理而成。 一 問題
資料庫SQL優化大總結之 百萬級資料庫面試優化方案
網上關於SQL優化的教程很多,但是比較雜亂。近日有空整理了一下,寫出來跟大家分享一下,其中有錯誤和不足的地方,還請大家糾正補充。 這篇文章我花費了大量的時間查詢資料、修改、排版,希望大家閱讀之後,感覺好的話推薦給更多的人,讓更多的人看到、糾正以及補充。 一、百萬級資料庫優化
53 Oracle資料庫SQL開發之 子查詢——編寫包含子查詢的UPDATE和DELETE
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
66 Oracle資料庫SQL開發之 高階查詢——使用線性迴歸函式
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!