查看執行計划


 
1.工具介紹
 
總結:單純估算用autotrace,真實調優用DBMS_XPLAN帶參數
 
1、explain
因為綁定變量的原因,這個只能是估算
explain plan for select 3+5 from dual;
select * from table(dbms_xplan.display());
select * from table(dbms_xplan.display(table_name=>'PLAN_TABLE',statement_id=>null,format=>'ALL'));
 
用explain plan解釋一個SQL,相關信息會默認被放到一個一個叫PLAN_TABLE的全局臨時表中。可以用這個來查看。
參數:
table_name,默認'PLAN_TABLE',如果別的一個表跟PLAN_TABLE有一樣的表結構,也可以讀取里面的信息。
statement_id 默認null,即查該session最后的一條explain plan解釋的語句。
format   默認'TYPICAL',全部是'BASIC','TYPICAL','ALL',ALL的時候會顯示PROJECTION, ALIAS and information about REMOTE SQL if the operation is distributed。其實除了指定這3個級別外,顯示什么信息也可以再通過后面的備注(減號代表去除相關信息)
'ALL -PROJECTION -NOTE'  #ALL級別,但不要投射與NOTE信息 
'BASIC ROWS'  --BASE下本來沒有ROWS信息,我們也可以給它加上。
還有其他選項,如:outline
每個連上來的用戶都可以使用plan_table,不用特別的權限,也不用讀取諸如v$plan這樣的視圖。
不會實際執行SQL,也不會在shared pool上生成該SQL的cursor,是生成了一個cursor不過是帶上explain plan for字眼的,而沒有獨立的該sql的cursor產生。
 
 
2、autotrace 
真實/估算,忽略綁定變量,非執行. 可以看邏輯讀等數量
SET AUTOTRACE
 
ON EXPLAIN                                                          只顯示執行計划                                         估算,因為沒執行
ON STATISTICS                                                     只顯示執行的統計信息                               
AUTOTRACE ON                                                    包含2,3兩項內容                                        真實,因為執行過 
AUTOTRACE TRACEONLY                                        與ON相似,但不顯示語句的執行結果              真實,因為執行過
 
3.SQL_TRACE 
在12c中文檔中提示:不再支持SQL_TRACE參數; 真實計划,需要用TKPROF工具解析,可以獲得綁定變量值. 
alter session set sql_trace=true;
alter session set sql_trace=false;
exec dbms_system.set_sql_trace_in_session(9,437,true)
exec dbms_system.set_sql_trace_in_session(9,437,false)
 
4.EVENT 10053 10046
真實計划,研究執行計划產生的原因
10046為增強版sql_trace
參考《10046事件》
參考《10046&10053的區別》
 
10053是檢查優化器行為的,實在搞不懂為什么走那個計划可以看看,用得較少。
10046可以檢查一些等待事件的內容,也可以獲取綁定變量,一般用得也比較少。
 
4.DBMS_XPLAN
真實計划
4.1 dbms_xplan.display_cursor
 
  1. DBMS_XPLAN.DISPLAY_CURSOR(                         
  2.  sql_id        IN  VARCHAR2  DEFAULT  NULL,        
  3.  child_number  IN  NUMBER    DEFAULT  NULL,        
  4.  format        IN  VARCHAR2  DEFAULT  'TYPICAL');  
 
IOSTATS:會展示該SQL的累計IO統計信息,加了last就顯示最后一個。
MEMSTATS:只有開啟了PGA自動內存管理,即pga_aggregate_target不是0,我們才能使用這項,會展示使用了多少memory,多少bytes被交換到磁盤,一般來說用了hash-join,sort,group by等比較需要內存的操作才會收集。
ALLSTATS:是'IOSTATS MEMSTATS'的同義詞。  IO+內存
LAST:默認地展示都是該游標的累積統計信息,加了LAST才會顯示最后一個。
RUNSTATS_TOT  --為了向后兼容,相當於IOSTATS
RUNSTATS_LAST --為了向后兼容,相當於IOSTATS LAST
 
 
查看該游標最后一次的實際統計信息執行計划
select * from table(dbms_xplan.display_cursor('fb8szhn9h5r95',null,'allstats last'));
 
會將該游標的累積執行信息列出,例如游標執行過兩次后,starts,A-Rows,buffers也是上面的兩倍
select * from table(dbms_xplan.display_cursor('fb8szhn9h5r95',null,'allstats'));
 
最詳細,匯集了普通模式的all與詳細模式的allstats,而且將默認不顯示的outline信息也顯示出來。
select * from table(dbms_xplan.display_cursor('fb8szhn9h5r95',null,'all allstats last outline'));
 
------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time | A-Rows | A-Time | Buffers | Reads |
------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | | 3 (100)| | 25 |00:00:00.01 | 3 | 2 |
|* 1 | COUNT STOPKEY | | 1 | | | | | 25 |00:00:00.01 | 3 | 2 |
| 2 | TABLE ACCESS FULL| T1 | 1 | 25 | 54400 | 3 (0)| 00:00:01 | 25 |00:00:00.01 | 3 | 2 |
------------------------------------------------------------------------------------------------------------------------------
 
gather_plan_statistics看更詳細的輸出--能達到10046的粒度了
alter session set statistics_level=all; 
select /*+ gather_plan_statistics */ from t1 where rownum<10;
 
Starts為該sql執行的次數。
E-Rows為執行計划預計的行數。
A-Rows為實際返回的行數。A-Rows跟E-Rows做比較,就可以確定哪一步執行計划出了問題。
A-Time為每一步實際執行的時間(HH:MM:SS.FF),根據這一行可以知道該sql耗時在了哪個地方。
Buffers為每一步實際執行的邏輯讀或一致性讀。
Reads為物理讀。
OMem、1Mem為執行所需的內存評估值,0Mem為最優執行模式所需內存的評估值,1Mem為one-pass模式所需內存的評估值。
0/1/M 為最優/one-pass/multipass執行的次數。
 
 
select t.* 
from v$sql s,table(dbms_xplan.display_cursor(s.sql_id,s.child_number,'ADVANCED ALLSTATS LAST')) t where s.sql_id = '&SQL_ID' ;
 
-----------------------------------------------------------------------------------------------------------
 
4.2 dbms_xplan.display_awr.   展示awr信息庫(因為shared pool中age out)中的執行計划--但是沒有謂詞條件
 
 
select * from table(dbms_xplan.display_awr('&sqlid',null,null,'ADVANCED +PEEKED_BINDS'));
 
 
參考《xplan.display_awr.sql》
 
sql_id   --輸入存儲在AWR中的sql_id,你可以先查dba_hist_sql_plan,dba_hist_sqltext,看看某個語句屬於什么sql_id。
plan_hash_value  --如果是null的話該sql_id所有的執行計划會輸出。默認null
db_id  --如果忽略,默認就是當前的database
format  --參考display(),還是'basic','typical','all'這樣,默認typical
權限:用戶需要select on DBA_HIST_SQL_PLAN,DBA_HIST_SQLTEXT,V$DATABASE的權限。
查sql_id,根據sql文本查出sql_id ,可以從dba_hist_sqltext查。
來源:展示的執行計划的信息,來源於dba_hist_sql_plan。
詳細:是否可以用allstats這樣查看更詳細的執行計划,這可能得取決於你當時的sql有沒開啟手機詳細運行時統計信息。
 
-----------------------------------------------------------------------------------------------------------
 
4.3 display_sql_plan_baseline   展示存儲在SPM中的SQL執行計划
查看SPM中baseline的執行計划:DBMS_XPLAN.DISPLAY_sql_plan_baseline
SELECT *  FROM table(DBMS_XPLAN.DISPLAY_sql_plan_baseline('SQL_a074c4f7bacd50da','SQL_PLAN_a0x64yyxcun6u06957ae0','ALL')); 
SELECT * FROM  table(DBMS_XPLAN.DISPLAY_sql_plan_baseline(sql_handle => 'SQL_351fadd1a0ec16be' ));
SELECT *  FROM table(DBMS_XPLAN.DISPLAY_sql_plan_baseline(plan_name => 'SQL_PLAN_a0x64yyxcun6u06957ae0','ALL')); 
 
格式:
sql_handle  SPM中的sql_handle相當於v$sql中的sql_id,默認Null
plan_name  SPM中唯一標識一個執行計划,就像v$sql中的plan_hash_value。默認null。如果是null,那么上面的sql_handle就必須指定。
format:參考display(),默認typical。
執行計划來源於:DBA_SQL_PLAN_BASELINES
 
 
5.各種現成腳本是利器
 
display_cursor_9i.sql.   —因為9i沒有display_cursor方法
printsql

 
2.執行計划閱讀順序:
由上至下:在執行計划中一般含有多個節點,相同級別(或並列)的節點,靠上的優先執行,靠下的后執行
從右向左:在某個節點下還存在多個子節點,先從最靠右的子節點開始執行。
 
靠光標大法即可,或者有些腳本里面帶了執行的步驟
 
標量子查詢 可能違反最右最上原則,參考《Oracle SQL優化分析步驟》
 
執行計划如果顯示是access,就表示這個謂詞條件的值將會影響數據的訪問路徑(表還是索引),而filter表示謂詞條件的值並不會影響數據訪問路徑,只起到過濾的作用
 
帶*號的是filter過濾 或 驅動access
 
 
動態采樣
如果在執行計划中有如下提示:
 
                     -dynamic sampling used for the statement
 
這提示用戶CBO當前使用的技術,需要用戶在分析計划時考慮到這些因素。 當出現這個提示,說明當前表使用了動態采樣。 我們從而推斷這個表可能沒有做過分析
這里會出現兩種情況:
(1)       如果表沒有做過分析,那么CBO可以通過動態采樣的方式來獲取分析數據,也可以或者正確的執行計划。
(2)       如果表分析過,但是分析信息過舊,這時CBO就不會在使用動態采樣,而是使用這些舊的分析數據,從而可能導致錯誤的執行計划。
在看執行計划的時候,除了看執行計划本身,還需要看謂詞和提示信息。 通過整體信息來判斷SQL 效率。
 
動態采樣適用范圍:
1.沒有統計信息,比如生成的中間臨時表
2.多列產生關聯,比如人為指定(11g還引入多列統計信息,但是是生成了一個列,代價大)


免責聲明!

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



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