Oracle 执行计划查看方法及优劣比较

执行计划六脉神剑

执行计划六脉神剑

一、explain plan for

set linesize 1000
set pagesize 2000
explain plan for
SELECT *
FROM t1, t2
WHERE t1.id = t2.t1_id
AND tl .n in (18, 19);
select * from table (dbms_xplan.display());

/*
优点 : 1. 无须真正执行,快捷方便
缺陷 1 .没有输出运行时的相关统计信息(产生多少逻辑读,多少次递归调用,多少次物理读的情况) ;
2 . 无法判断处理了多少行;
3 . 无法判断表被访问了多少次。
确实啊,这毕竟都没有真正执行又如何得知真实运行产生的统计信息。
*/


二、set autotrace on

/*
一优点。 1. 可以输出运行时的相关统计信息(产生多少逻辑读,多少次递归调用,多少次物理读的情况),
2 . 虽然必须要等语句执行完毕后才可以输出执行计划 , 但是可以有 traceonly 开关来控制返回结果不打屏输出。
一缺陷 1. 必须要等到语句真正执行完毕后,才可以出结果,
2. 无法看到表被访问了多少次。
*/

三、statistics_level=all
/*
步骤 1: alter session set statistics_level=all ;
步骤 2 :在此处执行你的 SQL
步骤 3: select* from table(dbms xplay.display_cursor(null , null,’allstats last'));
另注 a
1. 如果你用 /*+ gather_plan_statistics */ 的方法,可以省略步骤 1 ,直接执行步骤 2 , 3 。
2 . 关键字解读(其中 OMem、 lMem 和 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)中工作区的大小,
这个数据是由优化器统计数据以及前一次执行的性能数据估算得出的。
lMem :当工作区大小无法满足操作所需的大小时 , 需要将部分数据写入临时磁盘空间中(如果仅需要写入一次就可以
完成操作 , 就称一次通过,One-Pass; 否则为多次通过,Multi-Pass )。该列数据为语旬最后一次执行中,单次写磁盘所需要的内存大小 , 这个是由优化器统计数据以及前一次执行的性能数据估算得出的。
User -Mem : 语旬最后一次执行中,当前操作所使用的内存工作区大小 , 括号里面为(发生磁盘交换的次数 , 1 次即为One-Pass,大于 1 次则为 Multi-Pass,如果没有使用滋盘,则显示 OPTIMAL)
OMem、 lMem 为执行所需的内存评估值,OMem 为最优执行模式所需内存的评估值, lMem 为 one-pass 模式所需内
存的评估值。
0/1/M 为最优/one-pass/multipass 执行的次数。 Used-Mem 为消耗的内存.
*/

/*
--优点: 1. 可以清晰地从 ST阻TS 得出表被访问多少次;
2. 可以清晰地从 E-ROWS 和 A-ROWS 中得到预测的行数和真实的行数,从而可以准确判断 Oracle 评估是否准确;
3 . 虽然没有专门的输出运行时的相关统计信息,但是执行计划中的 BUFFERS 就是真实的逻辑读的数值。
--缺陷 1. 必须要等到语句真正执行完毕后,才可以出结果,
2 . 无法控制记录打屏输出,不像 autotrace 有 traceonly 可以控制不将结果打屏输出;
3 . 看不出递归调用的次数,看不出物理读的数值(不过逻辑读才是重点).
*/

四、 dbms_xplan.display_cursor 获取
/*
步骤 l select * from table(dbms_xplan.display_cursor('&sql_id'); (该方法是从共享池里得到)
注
1. 还有一个方法, select * from table(dbms_xplan.display_awr('&sql_id'); (这是从 awr 性能视图里获取)
2. 如果有多个执行计划,则可以用类似方法查出 :
select * from table(dbms_xplan.display_cursor(’cyzznbykb509s’,0));
select * from table(dbms_xplan.display_cursor('cyzznbykb509s’,1));
*/

/*
一优点,l.知道 sql_id 立即可得到执行计划,它和 explain plan for 一样无须执行,
2. 可以得到真实的执行计划。
一缺陷 1. 没有输出运行时的相关统计信息(产生多少逻辑读,多少次递归调用,多少次物理读的情况)
2 . 无法判断处理了多少行;
3. 无法判断表被访问了多少次。
*/

五、awrsqrpt.sql
步骤 1: @?/rdbms/admin/awrsqrpt.sql
步骤 2: 选择你要的断点( begin snap 和 end·snap)
步骤 3: 输入你的 sql_id

六、 10046 trace 跟踪
/*
步骤 1: alter session set events '10046 trace name context forever,level 12'; (开启跟踪)
步骤 2 执行 SQL 语旬
步骤 3: alter session set events '10046 trace name context off'; (关闭跟踪)
步骤 4 找到跟踪后产生的文件
步骤 5: tkprof trc 文件 目标文件 sys=no sort=prsela,exeela , fchela (格式化命令)
* /

步骤 4:
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;

tkprof /oracle/app/oracle/diag/rdbms/PROD/PRODSTB/trace/PROD_ora_7238.trc  /tmp/10046_sql.log sys=no sort=prsela,exeela,fchela

cat  /tmp/10046_sql.log
********************************************************************************

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      1.08       1.78       9568      10117          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        6      1.09       1.79       9568      10117          0           1

Misses in library cache during parse: 1

Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  SQL*Net message to client                       3        0.00          0.00
  SQL*Net message from client                     3       31.01         55.20
  db file sequential read                       130        0.01          0.13
  db file scattered read                        274        0.03          1.07


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.
********************************************************************************

/*
一优点: 1. 可以看出 SQL 语旬对应的等待事件,
2. 如果 SQL 语旬中有函数调用,函数中又有 SQL ,将会被列出,无处遁形,
3.可以方便地看出处理的行数,产生的物理逻辑读,
4 . 可以方便地看出解析时间和执行时间 i
5. 可以跟踪整个程序包。
一缺陷 1. 步骤烦琐,比较麻烦;
2. 无法判断表被访问了多少次,
3 . 执行计划中的谓词部分不能清晰地展现出来。
*/
复制代码

图片.png

差异何在

如果某 SOL 执行很长时间才出结果或返回不了结果,这时就只能用方法 1。
跟踪某条 SOL 最简单的方法是方法 1 ,其次就是方法 2。
如果想观察某条 SOL 多个执行计划的情况,只能用方法 4 和方法 5 。
如果 SOL 中含函数,函数中又套 SOL 等,即存在多层调用,想准确分析只能用方法 6。
要想确保看到真实的执行计划,不能用方法 1 和方法 2 。
要想获取表被访问的次数,只能使用方法 3 。

获取执行计划的方法汇总

获取执行计划的方法
方法 获取步骤 优点 缺点 应用场景
explain plan for 步骤1:explain plan for/跟上你要执行的SQL/ 步骤2:select * from table(dbms_xplan.display()); 无需真正执行,快捷方便 1.没有输出运行时的相关统计信息(产生多少逻辑读,多少次递归调用,多少次物理读的情况); 2.无法判断处理了多少行; 3.无法判断表被访问了多少次 如果某SQL执行很长时间才出结果或返回不了结果
set autotrace on 步骤1:set autotrace on 步骤2:在此处执行你的SQL 1.可以输出运行时的相关统计信息(产生多少逻辑读,多少次递归调用,多少次物理读的情况); 2.虽然必须要等语句执行完毕后才可以输出执行计划,但是可以有traceonly开关来控制返回结果不打屏输出 1.必须要等到语句真正执行完毕后,才可以出结果; 2.无法看到表被访问了多少次 想粗略知道recursive calls递归调用次数的方法用这个,详细用10046trace 方法
statistics_level=all 步骤1:alter session set statistics_level=all ; 步骤2:在此处执行你的SQL 步骤3:select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); 1.可以清晰地从STARTS得出表被访问多少次; 2.可以清晰的从E-ROWS和A-ROWS中得到预测的行数和真实的行数,从而可以准确判断Oracle评估是否准确。 3.虽然没有专门的输出运行时的相关统计信息,但是执行计划中的BUFFERS就是真实的逻辑读的数值 1.必须要等到语句真正执行完毕后,才可以出结果。 2.无法控制输出记录展现与否,而autotrace有 traceonly 可以控制不将输出记录打屏。 3.看不出递归调用的次数,看不出物理读的数值 要想获取表被访问的次数,只能使用方法3
dbms_xplan.display_cursor select * from table(dbms_xplan.display_cursor('&sq_id')); (该方法是从共享池里得到) 1.知道sql_id立即可得到执行计划,和explain plan for 一样无需执行; 2.可以得到真实的执行计划 1.没有输出运行时的相关统计信息(产生多少逻辑读,多少次递归调用,多少次物理读的情况); 2.无法判断处理了多少行; 3.无法判断表被访问了多少次 观察某条SQL有多条执行计划的情况
事件10046 trace跟踪 步骤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文件 目标文件 1.可以看出SQL语句对应的等待事件 2.如果SQL语句中有函数调用,SQL中有SQL,都将会被列出,无处遁形; 3.可以方便的看出处理的行数,产生的物理逻辑读; 4.可以方便地看出解析时间和执行时间; 5.可以跟踪整个程序包 1.步骤繁琐,比较麻烦; 2.无法判断表被访问了多少次; 3.执行计划中的谓词部分不能清晰的展现出来 如果SQL中含函数,函数中又套SQL等,即存在多层调用,想准确分析只能用该方法
awrsqrpt.sql 步骤1:@?/rdbms/admin/awrsqrpt.sql 步骤2:选择你要的断点(begin snap 和end snap) 步骤3:输入你的sql_id 可以方便地看到多个执行计划 获取的过程比较麻烦 想观察某条SQL多执行计划用该方法

SQLHC

和 explain plan for 一样的还可以使用 PL/SQL developer 工具的 F5 键也可查看执行计划,SQL Monitor 工具也可以查看,当然更高级的 sqlhc,上传 sqlhc 文件,输入 T 和 sqlid 即可生成。sqlhc是SQL health check的简称,能够收集sql相关的表、索引、统计信息、优化器参数、SQL执行情况、等待事件等信息,可以帮你检查SQL存在的问题并优化 SQL。

执行方法: sqlplus / as sysdba

SQL> @/home/oracle/tmp/sqlhc.sql T 9a4tv1dduu9u4

或者

SQL> @/home/oracle/tmp/sqlhc.sql

Parameter 1: Oracle Pack License (Tuning, Diagnostics or None) [T|D|N] (required)

Enter value for 1: T

PL/SQL procedure successfully completed.

Parameter 2: SQL_ID of the SQL to be analyzed (required)

Enter value for 2: 9a4tv1dduu9u4 <----输入 sql_id 等待 5 分钟左右

有可能更长或者更短(根据AWR保存周期、字典表大小不同相差较大,一般系统应该在5分钟以内能够完成),对数据库没有影响。执行过程有 log,也有屏显。执行过程会 insert 数据到 plan_table 表,执行结束会 rollback。

文件名以sqlhc开头,依次是日期、时间、sql_id。类似这样:sqlhc_20211125_1810_9a4tv1dduu9u4.zip

图片.png

其中4个html文件和log.zip是通常存在的。

10053 trace文件的生成需要11.2版本以上,sql_id仍在library cache内的情况下。

如果*sql_monitor.zip 也包含在sqlhc压缩包内,说明你的SQL执行时间超过了5s,或者是并行的SQL,而且收集sqlhc时仍保留在sql monitor的内存。sql monitor对分析sql执行计划有很大帮助,如果遇到问题收集sqlhc信息及时,就非常有可能收集到sql monitor文件。如果一个sql执行完后超过半小时没有收集sqlhc,sql monitor信息就就非常有可能被刷出内存。

主要分析的的3个html文件是:

*_health_check.html

*_diagnostics.html

*_execution_plan.html

内容非常丰富,可以多收集一些看看。

猜你喜欢

转载自juejin.im/post/7034455112080850951