【总结】Oracle查看SQL执行计划和运行效率指标的方法

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

---王鹏冲/20171212

一、oracle如何查看SQL执行计划:

方法1:
通过dbms_xplan.display_cursor来查看sql当前在内存中实际的执行计划(这个包实际就是从v$sql_plan里面取得的执行计划,做了封装和格式化):

display_cursor语法:
SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id'));
SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id',&child_number));
select * from table(dbms_xplan.display_cursor('&sql_id','&child_number','options'));

display_cursor的一些比较强大的options:

a. 'All'
b. 'advanced'
c. 'peeked_binds'
d. 'outline'
e. 'allstats last'

例如:
SQL> select * from table(dbms_xplan.display_cursor('c9cxqvr3q4tjd'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  c9cxqvr3q4tjd, child number 0
-------------------------------------
select count(0) from cat_product cp,cat_drug cd where cp.medical_id=cd.id

Plan hash value: 2559475106

-----------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name                     | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |                          |       |       |       |   750 (100)|          |
|   1 |  SORT AGGREGATE        |                          |     1 |    50 |       |            |          |
|*  2 |   HASH JOIN            |                          |   118K|  5804K|  4096K|   750   (1)| 00:00:11 |
|   3 |    INDEX FAST FULL SCAN| PK_CAT_DRUG              |   112K|  2758K|       |   186   (1)| 00:00:03 |
|   4 |    INDEX FAST FULL SCAN| TU_CAT_PRODUCT_MED_CHECK |   118K|  2902K|       |   212   (1)| 00:00:03 |
-----------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("CP"."MEDICAL_ID"="CD"."ID")
   


方法2:
查v$sql_plan里面的执行计划

方法3:
查dba_hist_sqlplan里面历史的执行计划。

方法4:
查看sql历史的执行计划(如果有改变,会有多个执行计划查出来): 
SELECT * FROM table(DBMS_XPLAN.DISPLAY_AWR('&sql_id',null,null,'ALL'));

方法5:
如果内存中找不到这个sql,那么可以通过plsql developer工具的查看执行计划的选项功能来查看,但是这个执行计划只是工具根据统计信息预估出来的,可能与实际的执行计划存在偏差的可能。


方法6:
如果内存中找不到这个sql,也可以通过如下这种方式来获取执行计划,但是这个执行计划只是工具根据统计信息预估出来的,可能与实际的执行计划存在偏差的可能。
EXPLAIN PLAN FOR ......select SQL_Statement......;
select * from table(dbms_xplan.display); 

二,如何知道sql的执行效率指标:
方法1:
查询v$sql里面的相关指标(适用于sql运行后,查看sql在内存中的实际效率),例如: 
select 
    a.sql_id, a.sql_text,
       a.PLAN_HASH_VALUE,
    round(a.BUFFER_GETS/a.EXECUTIONS) bg_per_exec,
    round(a.CPU_TIME/1000/a.EXECUTIONS) cpu_per_exec,
    round(a.ELAPSED_TIME/1000/a.EXECUTIONS) time_per_exec,      
    round(a.ROWS_PROCESSED/a.EXECUTIONS) rows_per_exec,
       a.EXECUTIONS,
       a.BUFFER_GETS,
       a.DISK_READS,
       a.CPU_TIME,
       a.ELAPSED_TIME,
       a.ROWS_PROCESSED
  from v$sql a
 where hash_value=377282797
 and cpu_time<>0
 and buffer_gets<>0
 and rows_processed<>0
order by sql_text
/


方法2:
---sql历史上逻辑读、物理读、执行时间的变化 (毫秒)
select b.begin_interval_time, a.sql_id,a.plan_hash_value,a.executions_delta,
round((a.buffer_gets_delta) /decode(nvl(a.executions_delta, 0),0,1, a.executions_delta),3) bg_per_exec,
round((a.disk_reads_delta) /decode(nvl(a.executions_delta, 0),0,1, a.executions_delta),3) diskr_per_exec,
round((a.cpu_time_delta/1000) /decode(nvl(a.executions_delta, 0),0,1, a.executions_delta),3) ctime_ms_per_exec,
round((a.elapsed_time_delta/1000) /decode(nvl(a.executions_delta, 0),0,1, a.executions_delta),3) etime_ms_per_exec,
round((a.APWAIT_DELTA/1000) /decode(nvl(a.executions_delta, 0),0,1, a.executions_delta),3) APWAIT_DELTA_ms_per_exec,
round((a.CCWAIT_DELTA/1000) /decode(nvl(a.executions_delta, 0),0,1, a.executions_delta),3) CCWAIT_DELTA_ms_per_exec,
round((a.rows_processed_delta) /decode(nvl(a.executions_delta, 0),0,1, a.executions_delta),3) row_process_per_exec
from dba_hist_sqlstat a, dba_hist_snapshot b 
where a.sql_id = '8hf3kwj1z14ch' 
and a.instance_number=b.instance_number
and a.instance_number=2 
and b.begin_interval_time> to_date('2017-10-05 09:00:00','yyyy-mm-dd hh24:mi:ss')
and b.begin_interval_time and a.snap_id=b.snap_id order by 1
;


方法3:
在oracle sqlplus客户端(plsql developer工具不支持),通过set autotrace来查看(适用于在测试库反复调试对比sql执行效率),例如:

SQL> set autotrace traceonly;  
SQL> select * from t2;  

  已选择402344行。  

执行计划  
----------------------------------------------------------  
Plan hash value: 1513984157  
  
--------------------------------------------------------------------------  
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |  
--------------------------------------------------------------------------  
|   0 | SELECT STATEMENT  |      |   402K|    33M|  1240   (3)| 00:00:15 |  
|   1 |  TABLE ACCESS FULL| T2   |   402K|    33M|  1240   (3)| 00:00:15 |  
--------------------------------------------------------------------------  
  
  
统计信息  
----------------------------------------------------------  
          0  recursive calls  
          0  db block gets  
          0  consistent gets  
          0  physical reads  
          0  redo size  
        911  bytes sent via SQL*Net to client  
        190  bytes received via SQL*Net from client  
          2  SQL*Net roundtrips to/from client  
          1  sorts (memory)  
          0  sorts (disk)  
     402344  rows processed  


/******set autotrace 详细选项******/
在SQL/PLUS的窗口运行以下命令 :
set time on;               (说明:打开时间显示) 
set timing on;             (说明:打开sql执行时间显示)
set autotrace on;          (说明:打开自动分析统计,并显示SQL语句的运行结果) 
set autotrace off;

用法: SET AUTOT[RACE] {OFF | ON | TRACE[ONLY]} [EXP[LAIN]] [STAT[ISTICS]]

举例:
SET AUTOT[RACE] OFF 停止AutoTrace
SET AUTOT[RACE] ON 开启AutoTrace,显示AUTOTRACE信息和SQL执行结果
SET AUTOT[RACE] TRACEONLY 开启AutoTrace,仅显示AUTOTRACE信息,不返回sql运行结果(在有大量行返回时比较有用,避免返回结果过多干扰)
SET AUTOT[RACE] ON EXPLAIN 开启AutoTrace,仅显示AUTOTRACE的EXPLAIN信息
SET AUTOT[RACE] ON STATISTICS开启AutoTrace,仅显示AUTOTRACE的STATISTICS信息

结果解释
consistent gets 逻辑读-一致性读
physical reads 物理读——执行SQL的过程中,从硬盘上读取的数据块个数
redo size      重做数——执行SQL的过程中,产生的重做日志的大小
bytes set via sql*net to client  通过sql*net发送给客户端的字节数
bytes received via sql*net from client  通过sql*net接受客户端的字节数
sorts(memory)  在内存中发生的排序
sorts(disk)    不能在内存中发生的排序,需要硬盘来协助
rows processed 结果的记录数 
/******set autotrace 详细选项******/

 

三、其它方法:
1,设置event
通过设置10046、10053 event trace

2,设置sql_trace

exec dbms_monitor.session_trace_enable;
exec dbms_monitor.database_trace_enable();
exec dbms_session.set_sql_trace(true);
exec dbms_system.set_sql_trace_in_session(sid,serial#,true);

exec dbms_monitor.session_trace_disable;
exec dbms_monitor.database_trace_disable();
exec dbms_session.set_sql_trace(false);
exec dbms_system.set_sql_trace_in_session(sid,serial#,false);
 

转载于:https://my.oschina.net/rocky0202/blog/1593597

你可能感兴趣的:(【总结】Oracle查看SQL执行计划和运行效率指标的方法)