oracle查看執行計划以及使用場景


文檔結構:

 

oracle執行計划使用場景

環境:

Centos 6.10

Oracle 18.3.0.0.0 c

 

11g默認啟動了自動統計信息收集的任務,默認運行時間是周一到周五晚上10點和周6,周天的早上6點,這種自動收集統計信息的方式並不是收集所有對象的統計信息,而是收集沒有統計信息的對象和統計信息過舊的對象。然后確定優先級,再開始進行統計信息。

Job 名稱是GATHER_STATS_JOB, 該Job收集數據庫所有對象的2種統計信息:

(1)Missing statistics(統計信息缺失)

(2)Stale statistics(統計信息陳舊)

以及對應的如下:

(1)對象的統計信息之前沒有收集過。

(2)當對象有超過10%的rows 被修改,此時對象的統計信息也稱為stale statistics。比如說白天truncate表了或者進行delete 超過10%的行。

  select window_name,

         window_next_time,

         autotask_status,

         optimizer_stats

    from DBA_AUTOTASK_WINDOW_CLIENTS;

 

 

 

select client_name,status from dba_autotask_client

 where client_name='auto optimizer stats collection';

 

  1. 統計信息
  2. 動態采樣

1. 統計信息默認情況下是每晚10點半后收集,如果新建對象還沒來得級收集統計信息,

就采用動態采樣的方式。

2. 具體在set autotrace 跟蹤的執行計划中,可以看到類似:- dynamic sampling

used for this statement (level=2)

3. 除非你用類似/*+dynamic_sampling(t 0) */的HINT關閉這個動態采樣。

4. 在收集過統計信息后,Oracle就不會采用動態采樣。

注:建索引過程中,默認會收集索引相關的統計信息。

set autotrace off

set linesize 1000

drop table t_sample purge;

create table t_sample as select * from dba_objects;

create index idx_t_sample_objid on t_sample(object_id);

 select num_rows, blocks, last_analyzed from user_tables

 where table_name = 'T_SAMPLE';

 

 

 

--建索引后,自動收集統計信息。

select index_name,

       num_rows,

       leaf_blocks,

       distinct_keys,

       last_analyzed

  from user_indexes

 where table_name = 'T_SAMPLE';

 

 

  

select  * from t_sample where object_id=20;

 

 

 可以查看那個是動態采樣

 

exec dbms_stats.gather_table_stats(ownname => 'sys',tabname => 'T_SAMPLE',estimate_percent => 10,method_opt=> 'for all indexed columns',cascade=>TRUE) ;

set autotrace off

select num_rows, blocks, last_analyzed

       from user_tables

      where table_name = 'T_SAMPLE';

 

 

 可以查看到有最后一次統計信息收集的時間了。

 以下是平時分區表印記分區索引,直方圖,統計信息收集的一些筆記:

--查看表的情況

select table_name,num_rows, blocks, empty_blocks, avg_space, chain_cnt, avg_row_len,last_analyzed from user_tables; --普通表
select * from user_tab_partitions;--分區表
select table_name,partition_name,subpartition_name,num_rows, blocks, empty_blocks, avg_space, chain_cnt, avg_row_len,last_analyzed from user_tab_subpartitions; --子分區
select table_name,
partitioning_type,
subpartitioning_type,
partition_count
from user_part_tables
where subpartitioning_type <> 'NONE'; --查看分區表中帶子分區的個數

--當前用戶下,某個分區的記錄數是平均記錄數的2倍以上
set linesize 266
col table_name format a20
select table_name,
max(num_rows),
trunc(avg(num_rows),0),
sum(num_rows),
trunc(max(num_rows) / sum(num_rows),2),
count(*)
from user_tab_partitions
group by table_name
having max(num_rows) / sum(num_rows) > 2 / count(*);

--查看有子分區的數據情況:
select table_name,partition_name,subpartition_name,
num_rows


--索引列的統計信息
BLEVEL, --索引的層數
LEAF_BLOCKS, --葉子結點的個數
DISTINCT_KEYS, --唯一值的個數
AVG_LEAF_BLOCKS_PER_KEY, --每個KEY的平均葉塊個數
AVG_DATA_BLOCKS_PER_KEY, --每個KEY的平均數據塊個數
CLUSTERING_FACTOR --群集因子

select index_name,table_name,blevel, leaf_blocks, distinct_keys, avg_leaf_blocks_per_key,avg_data_blocks_per_key, clustering_factor from user_indexes; --普通表

select index_name,"COMPOSITE",SUBPARTITION_COUNT,PARTITION_NAME,blevel, leaf_blocks, distinct_keys, avg_leaf_blocks_per_key,avg_data_blocks_per_key, clustering_factor from user_ind_partitions --分區表

--查看普通索引失效:
select t.index_name,
t.table_name,
blevel,
t.num_rows,
t.leaf_blocks,
t.distinct_keys
from user_indexes t
where status = 'INVALID';

--查看分區索引失效:
select t.index_name,
t.table_name,
blevel,
t.num_rows,
t.leaf_blocks,
t.distinct_keys
from user_ind_subpartitions t
where index_name in (select index_name from user_indexes)
and status = 'INVALID'

--查看子分區索引
select t.index_name,
t.partition_name,
blevel,
t.num_rows,
t.leaf_blocks,
t.distinct_keys
from user_ind_subpartitions t
where index_name in (select index_name from user_indexes)
and status = 'INVALID'


分區表和子分區表
select index_name,PARTITION_NAME,SUBPARTITION_NAME,blevel,leaf_blocks,distinct_keys, avg_leaf_blocks_per_key,avg_data_blocks_per_key, clustering_factor from user_ind_subpartitions; --子分區表

查看直方圖:
SELECT table_name,column_name, num_distinct,low_value, high_value, density, num_nulls, num_buckets, histogram from user_tab_columns;

select * from user_tab_histograms;
select * from user_part_histograms;
select * from user_subpart_histograms;

查看列的信息:
NUM_DISTINCT, --唯一值的個數
LOW_VALUE, --列上的最小值
HIGH_VALUE, --列上的最大值
DENSITY, --選擇率因子(密度)
NUM_NULLS, --空值的個數
NUM_BUCKETS, --直方圖的BUCKET個數
HISTOGRAM --直方圖的類型
直方圖是一種列的特殊的統計信息,主要用來描述列上的數據分布情況,
SELECT table_name,column_name, num_distinct,low_value, high_value, density, num_nulls, num_buckets, histogram from user_tab_columns ;
直方圖:直方圖意義:在oracle數據庫中,CBO會默認認為目標列的數據量在其最小值和最大值之間是均勻分布的(最小值最大值不准確會導致謂詞越界),
並且會按照這個均勻分布原則來計算對目標列事假的where查詢條件后的可選這率及結果集的cardinality,進而據此來計算成本值並選擇執行計划。但是,目標列的數據是均勻分布的按照這個原則選擇執行計划是正確的;
如果目標數據列分布不均勻,甚至是嚴重傾斜,分布極度不均勻,那么這個按照這個原則選擇執行計划就不合適,甚至是錯誤的,為此我們需要對那些數據分布不均勻的列進行直方圖收集。

直方圖實際存儲在數據字典sys.histgrm$中,可以通過數據字典dba_tab_historgrams,dba_part_histograms和dba_subpart_histograms來分別查看表,分區表的分區和分區表的子分區的直方圖信息。


收集統計信息的語句:
analyze 命令的語法如下:
analyze table tablename compute statistics;
analyze table tablename compute statistics for all indexes;
analyze table tablename delete statistics;
dbms_stats.gather_table_stats 收集表、列和索引的統計信息;
dbms_stats.gather_schema_stats 收集SCHEMA下所有對象的統計信息;
dbms_stats.gather_index_stats 收集索引的統計信息;
dbms_stats.gather_system_stats 收集系統統計信息

表統計信息的查看:
包含表行數,使用的塊數,空的塊數,塊的使用率,行遷移和鏈接的數量,pctfree,pctused的數據,行的平均大小:
NUM_ROWS, --表中的記錄數
BLOCKS, --表中數據所占的數據塊數
EMPTY_BLOCKS, --表中的空塊數
AVG_SPACE, --數據塊中平均的使用空間
CHAIN_CNT, --表中行連接和行遷移的數量
AVG_ROW_LEN --每條記錄的平均長度

統計信息的收集:
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(ownname => 'hr',
tabname => 'employees',
estimate_percent => 100,
method_opt => 'for all columns size',
no_invalidate => FALSE,
degree => 1,
cascade => TRUE);
END;
/

刪除直方圖的影響:
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(
ownname => 'hr',
tabname => 'employees',
estimate_percent => 100,
method_opt => 'for all columns size 1',
no_invalidate => FALSE,
degree => 1,
cascade => TRUE);
END;
/

for all columns size 1 為所有size 放在一個桶里面(即為刪除)

select a.table_name,a.column_name,
b.num_rows,
a.num_distinct Cardinality,
round(a.num_distinct / b.num_rows * 100, 2) selectivity,
a.histogram,
a.num_buckets
from user_tab_col_statistics a, user_tables b
where
a.table_name = b.table_name

oracle 一般查詢數據行數在5%及以下,用到索引過略字段,CBO會走索引
生成了直方圖之后 執行以下兩個句子查看一下分別的執行計划對比看看

NUM_ROWS 表示總行數
CARDINALITY 表示基數
SELECTIVITY表示選擇性 選擇性在10%以上都比較高了
HISTOGRAM表示直方圖的類型:
FREQUECNCY頻率直方圖、 當列中Distinct_keys 較少(小於254),如果不手工指定直方圖桶數(BUCKET),Oracle就會自動的創建頻率直方圖,並且桶數(BUCKET)等於Distinct_Keys。
HEIGHT BALANCED 高度平衡直方圖 當列中Distinct_keys大於254,如果不手工指定直方圖桶數(BUCKET),Oracle就會自動的創建高度平衡直方圖。
NONE表示未收集直方圖
NUM_BUCKETS 表示桶數

3、疑問使用直方圖的場合

1、直方圖到底應該什么時候收集直方圖?
就查一下執行計划和實際查詢行數進行比較 估算的基數ROWS是不是算錯了。
構造直方圖最主要的原因就是幫助優化器在表中數據嚴重偏斜時做出更好的規划
注意:如果查詢不引用該列,則創建直方圖沒有意義。這種錯誤很常見,許多 DBA 會在偏差列上創建柱狀圖,即使沒有任何查詢引用該列。
2、只對有索引的列收集直方圖也是錯的!
3、直方圖究竟是干嘛的?
告訴CBO 有沒有收集直方圖 這個列是不是均衡的
1. 沒收集直方圖 ---CBO認為這個列是分布均勻的
2. 收集過了 ---告訴CBO這個列數據有問題 分布不均衡,特別是頻率直方圖算的會很准

最終就是影響rows

 

獲取執行計划的6種方法

1. explain plan for獲取

2. set autotrace on

3. statistics_level=all

4. 通過dbms_xplan.display_cursor輸入sql_id參數直接獲取

5. 10046 trace跟蹤

6. awrsqrpt.sql

 

方法1(explain plan for)

類似PLSQL DEVELOPER里的F5

/*

  步驟1:explain plan for "你的SQL"

  步驟2:select * from table(dbms_xplan.display());

*/

set linesize 1000

set pagesize 2000

explain plan for

SELECT  *

FROM t1, t2

WHERE t1.id = t2.t1_id

AND t1.n in(18,19);

select * from table(dbms_xplan.display());

 

 

 

優點:  1.無需真正執行,快捷方便

缺陷:  1.沒有輸出運行時的相關統計信息(產生多少邏輯讀,多少次遞歸調用,多少次物理讀的情況);

        2.無法判斷是處理了多少行;

        3.無法判斷表被訪問了多少次。

 

確實啊,這畢竟都沒有真正執行又如何得知真實運行產生的統計信息。

方法2(set autotrace on 方式)

 

有如下幾種方式:

                     set autotrace on                 (得到執行計划,輸出運行結果)

                     set autotrace traceonly          (得到執行計划,不輸出運行結果)

                     set autotrace traceonly explain  (得到執行計划,不輸出運行結果和統計信息部分,僅展現執行計划部分)

                     set autotrace traceonl statistics(不輸出運行結果和執行計划部分,僅展現統計信息部分)

 

set autotrace on

SELECT  *

FROM t1, t2

WHERE t1.id = t2.t1_id

AND t1.n in(18,19);

 

 

 

優點:1.可以輸出運行時的相關統計信息(產生多少邏輯讀,多少次遞歸調用,多少次物理讀的情況);

        2.雖然必須要等語句執行完畢后才可以輸出執行計划,但是可以有traceonly開關來控制返回結果不打屏輸出。

方法3(statistics level=all的方式) 

  步驟1:alter session set statistics_level=all ;

  步驟2:在此處執行你的SQL

  步驟3:select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

 

 

set autotrace off   

alter session set statistics_level=all ;

SELECT  *

FROM t1, t2

WHERE t1.id = t2.t1_id

AND t1.n in(18,19);

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

 

 

 

 

另注:

 

  1. 如果你用 /*+ gather_plan_statistics */的方法,可以省略步驟1,直接步驟2,3。

  2. 關鍵字解讀(其中OMem、1Mem和User-Mem在后續的課程中會陸續見到):

    Starts為該sql執行的次數。

    E-Rows為執行計划預計的行數。

    A-Rows為實際返回的行數。A-Rows跟E-Rows做比較,就可以確定哪一步執行計划出了問題。

    A-Time為每一步實際執行的時間(HH:MM:SS.FF),根據這一行可以知道該sql耗時在了哪個地方。

    Buffers為每一步實際執行的邏輯讀或一致性讀。

    Reads為物理讀。

    OMem:當前操作完成所有內存工作區(Work Aera)操作所總共使用私有內存(PGA)中工作區的大小,

         這個數據是由優化器統計數據以及前一次執行的性能數據估算得出的

    1Mem:當工作區大小無法滿足操作所需的大小時,需要將部分數據寫入臨時磁盤空間中(如果僅需要寫入一次就可以完成操作,

         就稱一次通過,One-Pass;否則為多次通過,Multi_Pass).該列數據為語句最后一次執行中,單次寫磁盤所需要的內存

         大小,這個由優化器統計數據以及前一次執行的性能數據估算得出的

    User-Mem:語句最后一次執行中,當前操作所使用的內存工作區大小,括號里面為(發生磁盤交換的次數,1次即為One-Pass,

           大於1次則為Multi_Pass,如果沒有使用磁盤,則顯示OPTIMAL)

    OMem、1Mem為執行所需的內存評估值,0Mem為最優執行模式所需內存的評估值,1Mem為one-pass模式所需內存的評估值。

    0/1/M 為最優/one-pass/multipass執行的次數。Used-Mem耗的內存

--優點:1.可以清晰的從STARTS得出表被訪問多少。

        2.可以清晰的從E-ROWS和A-ROWS中得到預測的行數和真實的行數,從而可以准確判斷Oracle評估是否准確。

        3.雖然沒有專門的輸出運行時的相關統計信息,但是執行計划中的BUFFERS就是真實的邏輯讀的多少

--缺陷:1.必須要等到語句真正執行完畢后,才可以出結果。

        2.無法控制記錄輸屏打出,不像autotrace有 traceonly 可以控制不將結果打屏輸出。

        3.看不出遞歸調用的次數,看不出物理讀的多少(不過邏輯讀才是重點)

方法4(dbms_xplan.display_cursor)

select  * from table(dbms_xplan.display_cursor('&sq_id')); (該方法是從共享池里得到)

注:

  1. 還有一個方法,select  * from table(dbms_xplan.display_awr('&sq_id'));(這是awr性能視圖里獲取到的)

  2. 如果有多執行計划,可以用類似方法查出

先通過v$sql查看sql_id:

    select * from table(dbms_xplan.display_cursor('1a914ws3ggfsn',0));

select * from table(dbms_xplan.display_cursor('1a914ws3ggfsn',1));

這個好處就是可以查看該sql多個執行計划

 

 

 

從中可以看出:

--優點:1.知道sql_id立即可得到執行計划,和explain plan for 一樣無需執行;

        2.可以得到真實的執行計划。(停,等等,啥真實的,剛才這幾個套路中,還有假的執行計划的嗎?)

--缺陷  1.沒有輸出運行時的相關統計信息(產生多少邏輯讀,多少次遞歸調用,多少次物理讀的情況);

        2.無法判斷是處理了多少行; 

        3.無法判斷表被訪問了多少次。

 

方法5(10046TRACE)

(10046TRACE)

 

  步驟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  (格式化命令)    

 

set autotrace off

alter session set statistics_level=typical;    

alter session set events '10046 trace name context  forever,level 12';

 

SELECT  *

FROM t1, t2

WHERE t1.id = t2.t1_id

AND t1.n in(18,19);  

  

alter session set events '10046 trace name context off';  

 

12c之前查看trace文件:

 

select d.value

|| '/'

|| LOWER (RTRIM(i.INSTANCE, CHR(0)))

|| '_ora_'

|| p.spid

|| '.trc' trace_file_name

from (select p.spid

      from v$mystat m,v$session s, v$process p

      where  m.statistic#=1 and s.sid=m.sid and p.addr=s.paddr) p,

      (select t.INSTANCE

       FROM v$thread t,v$parameter v

       WHERE v.name='thread'

       AND(v.VALUE=0 OR t.thread#=to_number(v.value))) i,

       (select value

       from v$parameter

       where name='user_dump_dest') d;

      

12c之后 查看trace文件:

 

select d.value

|| '/'

|| LOWER (RTRIM(i.INSTANCE, CHR(0)))

|| '_ora_'

|| p.spid

|| '.trc' trace_file_name

from (select p.spid

      from v$mystat m,v$session s, v$process p

      where  m.statistic#=1 and s.sid=m.sid and p.addr=s.paddr) p,

      (select t.INSTANCE

       FROM v$thread t,v$parameter v

       WHERE v.name='thread'

       AND(v.VALUE=0 OR t.thread#=to_number(v.value))) i,

       (select value from v$diag_info where  name='Diag Trace') d;

 exit

tkprof  /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_17496.trc /home/oracle/10046.txt

 

 

 

 

more  /home/oracle/10046.txt

 

TKPROF: Release 18.0.0.0.0 - Development on Sat Oct 12 14:48:05 2019

 

Copyright (c) 1982, 2018, Oracle and/or its affiliates.  All rights reserved.

 

Trace file: /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_17496.trc

Sort options: default

 

********************************************************************************

count    = number of times OCI procedure was executed

cpu      = cpu time in seconds executing

elapsed  = elapsed time in seconds executing

disk     = number of physical reads of buffers from disk

query    = number of buffers gotten for consistent read

current  = number of buffers gotten in current mode (usually for update)

rows     = number of rows processed by the fetch or execute call

********************************************************************************

 

SELECT  *

FROM t1, t2

WHERE t1.id = t2.t1_id

AND t1.n in(18,19)

 

call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        2      0.00       0.00          0         14          0           2

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total        4      0.00       0.00          0         14          0           2

 

Misses in library cache during parse: 0

Optimizer mode: ALL_ROWS

Parsing user id: SYS

Number of plan statistics captured: 1

 

Rows (1st) Rows (avg) Rows (max)  Row Source Operation

---------- ---------- ----------  ---------------------------------------------------

         2          2          2  HASH JOIN  (cr=14 pr=0 pw=0 time=474 us starts=1 cost=8 size=250 card=2)

         2          2          2   NESTED LOOPS  (cr=14 pr=0 pw=0 time=467 us starts=1 cost=8 size=250 card=2)

         2          2          2    NESTED LOOPS  (cr=12 pr=0 pw=0 time=584 us starts=1 cost=8 size=250 card=2)

         2          2          2     STATISTICS COLLECTOR  (cr=7 pr=0 pw=0 time=434 us starts=1)

         2          2          2      INLIST ITERATOR  (cr=7 pr=0 pw=0 time=395 us starts=1)

         2          2          2       TABLE ACCESS BY INDEX ROWID BATCHED T1 (cr=7 pr=0 pw=0 time=391 us starts=2 cost=4 size=118 car

d=2)

         2          2          2        INDEX RANGE SCAN T1_N (cr=5 pr=0 pw=0 time=347 us starts=2 cost=2 size=0 card=2)(object id 741

71)

         2          2          2     INDEX RANGE SCAN T2_T1_ID (cr=5 pr=0 pw=0 time=147 us starts=2 cost=1 size=0 card=1)(object id 74

172)

         2          2          2    TABLE ACCESS BY INDEX ROWID T2 (cr=2 pr=0 pw=0 time=35 us starts=2 cost=2 size=66 card=1)

         0          0          0   TABLE ACCESS FULL T2 (cr=0 pr=0 pw=0 time=0 us starts=0 cost=2 size=66 card=1)

 

 

Elapsed times include waiting on following events:

  Event waited on                             Times   Max. Wait  Total Waited

  ----------------------------------------   Waited  ----------  ------------

  Disk file operations I/O                        1        0.00          0.00

  SQL*Net message to client                       2        0.00          0.00

  SQL*Net message from client                     2        7.36          7.36

********************************************************************************

 

SQL ID: 06nvwn223659v Plan Hash: 0

 

alter session set events '10046 trace name context off'

 

 

call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        0      0.00       0.00          0          0          0           0

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total        2      0.00       0.00          0          0          0           0

 

Misses in library cache during parse: 0

Parsing user id: SYS

 

 

 

********************************************************************************

 

OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS

 

call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        2      0.00       0.00          0          0          0           0

Execute      2      0.00       0.00          0          0          0           0

Fetch        2      0.00       0.00          0         14          0           2

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total        6      0.00       0.00          0         14          0           2

 

Misses in library cache during parse: 0

 

Elapsed times include waiting on following events:

  Event waited on                             Times   Max. Wait  Total Waited

  ----------------------------------------   Waited  ----------  ------------

  Disk file operations I/O                        2        0.00          0.00

  SQL*Net message to client                       3        0.00          0.00

  SQL*Net message from client                     3        7.36         14.08

 

 

OVERALL TOTALS FOR ALL RECURSIVE STATEMENTS

 

call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        0      0.00       0.00          0          0          0           0

Execute      0      0.00       0.00          0          0          0           0

Fetch        0      0.00       0.00          0          0          0           0

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total        0      0.00       0.00          0          0          0           0

 

Misses in library cache during parse: 0

 

    2  user  SQL statements in session.

    0  internal SQL statements in session.

    2  SQL statements in session.

********************************************************************************

Trace file: /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_17496.trc

Trace file compatibility: 12.2.0.0

Sort options: default

 

       1  session in tracefile.

       2  user  SQL statements in trace file.

       0  internal SQL statements in trace file.

       2  SQL statements in trace file.

       2  unique SQL statements in trace file.

      66  lines in trace file.

       7  elapsed seconds in trace file.

 

--優點:1.可以看出SQL語句對應的等待事件(這個是level 12,0,4,8對應的是其他情況)

        2.如果SQL語句中有函數調用,SQL中有SQL,將會都被列出,無處遁形。

        3.可以方便的看出處理的行數,產生的物理邏輯讀。

        4.可以方便的看出解析時間和執行時間。

        5.可以跟蹤整個程序包

       

--缺陷: 1.步驟繁瑣,比較麻煩

        2.無法判斷表被訪問了多少次。

        3.執行計划中的謂詞部分不能清晰的展現出來。

 

方法6. awrsqrpt.sql  

 

  步驟1:@?/rdbms/admin/awrsqrpt.sql

  步驟2:選擇你要的斷點(begin snap 和end snap)

  步驟3:輸入你的sql_id    

 

 

結論

 

6種方法各自適用場合

1.如果某SQL執行很長時間才出結果戒返回丌了結果,這時就只能用方法1;

2.跟蹤某條SQL最簡單的方法是方法1,其次就是方法2;

3.如果想觀察到某條SQL有多條執行計划的情況,只能用方法4和方法6;

4.如果SQL中含有函數,函數中套有SQL等多層調用,想准確分析只能使用方法5;

5.要想確保看到真實的執行計划,丌能用方法1和方法2;

6.要想獲取表被訪問的次數,只能使用方法3;

 

不真實的執行計划

執行計划中"真實執行計划” 是一個很重要的常識,這也就是方法1 和方法2 的最大缺陷了。  狠狠揪出本次即將被批斗的壞蛋:方法1的explain plan for和方法2的set autotrace on

例子主要是針對:綁定變量窺視與直方圖

---構建T表,數據,及主鍵

---構建T表,數據,及主鍵

 

DROP TABLE t;

CREATE TABLE t

AS

SELECT rownum AS id, rpad('*',100,'*') AS pad

FROM dual

CONNECT BY level <= 1000;

ALTER TABLE t ADD CONSTRAINT t_pk PRIMARY KEY (id);

---收集統計信息

BEGIN

  dbms_stats.gather_table_stats(

    ownname          => user,

    tabname          => 'T',

    estimate_percent => 100,

    method_opt       => 'for all columns size 254'

  );

END;

/

 

  下面我們將會用多種方法來查看如下語句的執行計划

VARIABLE id NUMBER

COLUMN sql_id NEW_VALUE sql_id 

EXECUTE :id := 990;

SELECT count(pad) FROM t WHERE id < :id;

EXECUTE :id := 10;

SELECT count(pad) FROM t WHERE id < :id;

 

利用以上6中方法查看執行計划是否真實:

----方法1(explain plan for 的方式。類似PLSQL DEVELOPE里的F5)

set linesize 1000

set pagesize 2000

VARIABLE id NUMBER

COLUMN sql_id NEW_VALUE sql_id

EXECUTE :id := 990;

explain plan for

SELECT count(pad) FROM t WHERE id < :id;

select * from table(dbms_xplan.display());

 

 

 

 

走的是索引范圍掃描

 

----方法2(set autotrace on 方式)

set autotrace traceonly

VARIABLE id NUMBER

COLUMN sql_id NEW_VALUE sql_id

EXECUTE :id := 990;

SELECT count(pad) FROM t WHERE id < :id;

 

 

 

也是索引范圍掃描

 

----方法3(statistics level=all的方式)

set autotrace off         

alter session set statistics_level=all ;

VARIABLE id NUMBER

COLUMN sql_id NEW_VALUE sql_id

EXECUTE :id := 990;

SELECT count(pad) FROM t WHERE id < :id;

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

 

 

 

看到沒有,全表掃描。

----方法4(知道sql_id后,直接帶入的方式)

select * from table(dbms_xplan.display_cursor('asth1mx10aygn'));

 

 

 

 

也是全表掃描

 

----方法5(10046TRACE)

set autotace off

alter session set statistics_level=typical;    

alter session set events '10046 trace name context  forever,level 12';

VARIABLE id NUMBER

COLUMN sql_id NEW_VALUE sql_id

EXECUTE :id := 990;

SELECT count(pad) FROM t WHERE id < :id;

  

alter session set events '10046 trace name context off';  

 

12c之后 查看trace文件:

select d.value
|| '/'
|| LOWER (RTRIM(i.INSTANCE, CHR(0)))
|| '_ora_'
|| p.spid
|| '.trc' trace_file_name
from (select p.spid
from v$mystat m,v$session s, v$process p
where m.statistic#=1 and s.sid=m.sid and p.addr=s.paddr) p,
(select t.INSTANCE
FROM v$thread t,v$parameter v
WHERE v.name='thread'
AND(v.VALUE=0 OR t.thread#=to_number(v.value))) i,
(select value from v$diag_info where name='Diag Trace') d;

 

 

 

查看轉換的文件:

 

 

 

也是全表掃描

 

一條SQL對應多個執行計划

執行計划中"一條SQL對應多個計划” 也是一個很重要的常識,這只能靠方法4和方法6了。

方法4的dbms_xplan.display_cursor+sql_id和方法6的awrsqrpt.sql

sys用戶登錄測試(切換了pdb):

DROP TABLE t;

CREATE TABLE t AS SELECT * FROM DBA_OBJECTS where object_id is not null;

create index idx_object_id on t(object_id);

alter table T modify object_id not null;

set autotrace off 

set linesize 1000

set pagesize 2000       

alter session set statistics_level=all ;

select count(*) from t;

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

 

 

 

 

C##test用戶登錄測試(切換了pdb):

drop table t purge;

CREATE TABLE t AS SELECT rownum id ,rownum+1 n FROM DBA_OBJECTS ;

set autotrace off 

set linesize 1000 

set pagesize 2000              

alter session set statistics_level=all ;

select count(*) from t;

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

 

 

 

 

可以查看是有兩個(貌似pdb里面查詢結果不對)

select sql_id, child_number from v$sql  where sql_id='cyzznbykb509s';

SQL_ID        CHILD_NUMBER

------------- ------------

cyzznbykb509s            0

cyzznbykb509s            1

 

特別說明一下,第6種獲取執行計划的方法awrsqrpt.sql同樣也可以獲取到多條執行計划

這個方法當一條SQL有多個執行計划的時候,可以在報表里輸出。但是要確保在AWR的采集周期內的生成報表。


免責聲明!

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



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