博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Oracle中如何得到真实的执行计划
阅读量:6090 次
发布时间:2019-06-20

本文共 5880 字,大约阅读时间需要 19 分钟。

之前介绍过4种在Oracle数据库里查看执行计划的方法

  • explain plan 命令

  • DBMS_XPLAN

  • SQLPLUS中的AUTOTRACE开关

  • 10046事件

其中除了第四种方法之外,其他三种方法得到的执行计划都有可能是不准确的。在Oracle中判断得到的执行计划是否是准确,就是看目标SQL是否被真正执行,真正执行过的SQL所对应的执行计划就是准确的,反之则有可能不准。但是这里的判断原则从严格意义上来说并不适用于AUTOTRACE开关,因为所有的AUTOTRACE开关所显示的执行计划都可能是不准的,即使对应的目标SQL实际上已经执行过。

下面我们就用上述原则来判断除第4种以外的其他三种方法中哪些得到的执行计划是准的,哪些方法得到的执行计划有可能不准。

1explain plan命令

对这种方法得到的执行计划而言,因为此时的目标SQL并没有被实际执行,所以该方法得到的执行计划有可能是不准的,尤其是目标SQL包含绑定变量时。在默认开启绑定变量窥探(Bind Peeking)的情况,对含绑定变量的目标SQL使用explain plan得到的执行计划只是一个半成品,Oracle在随后对该SQL的绑定变量进行窥探后就得到了这些绑定变量具体的值,此时Oralce可能会对上述半成品的执行计划做调整,一量做了调整,使用explain plan命令得到的执行计划就不准了。

2DBMS_XPLAN

对于这种方法而言,针对不同的应用场景,可以选择如下四种方式中的一种:

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

  2. select * from     table(dbms_xplan.display_cursor(null,null,'advanced'));

  3. select * from     table(dbms_xplan.display_cursor('sql_id/hash_value',child_cursor_number,'advanced'));

  4. select * from     table(dbms_xplan.display_awr('sql_id'));

显然,执行select * from table(dbms_xplan.display)得到的执行计划可能是不准的,因为它只是用于查看使用explain plan命令得到的目标SQL的执行计划,目标SQL此时还没有被真正执行,所以用它得到的执行计划可能是不准的。使用剩下的三种方式得到的执行计划都是准的,因为此时目标SQL都已经被实际执行过了。

3AUTOTRACE开关

使用这种方法,可以选择如下三种方式来开启TRACE开关

  • SET AUTOTRACE ON

  • SET AUTOTRACE TRACEONLY

  • SET AUTOTRACE TRACEONLY     EXPLAIN

上述三种方法中,当使用SET AUTOTRACE ONSET AUTOTRACE TRACEONLY时,目标SQL都已经被实际执行过了,正是因为被实际执行过,所以SET AUTOTRACE ONSET AUTOTRACE TRACEONLY的情况下我们能看到目标SQL的实际资源消耗情况。当使用SET AUTOTRACE TRACEONLY EXPLAIN时,如果执行的是SELECT语句,则该SELECT语句并没有被Oracle实际执行,但如果执行的是DML语句,情况就不一样了,此时的DML语句会被Oracle实际执行的。虽然使用部分SET AUTOTRACE命令后目标SQL实际上已经执行过了,但所得到的执行计划有可能是不准的,因为使用SET AUTOTRACE命令所显示的执行计划都是来源于调用explain plan命令。

下面使用一个例子证明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
scott@ORCL>
create 
table 
t1 
as 
select 
from 
dba_objects;
 
Table 
created.
 
scott@ORCL>
insert 
into 
t1 
select 
from 
t1;
 
86885 
rows 
created.
 
scott@ORCL>
commit
;
 
Commit 
complete.
 
scott@ORCL>
select 
count
(*) 
from 
t1;
 
  
COUNT
(*)
----------
    
173770
 
scott@ORCL>
create 
index 
idx_t1 
on 
t1(object_id);
 
Index 
created.
 
scott@ORCL>
exec 
dbms_stats.gather_table_stats(ownname=>
'SCOTT'
,tabname=>
'T1'
,estimate_percent=>100,
cascade
=>
true
);
 
PL/SQL 
procedure 
successfully completed.
 
scott@ORCL>var x number;
scott@ORCL>var y number;
scott@ORCL>
exec 
:x := 0;
 
PL/SQL 
procedure 
successfully completed.
 
scott@ORCL>
exec 
:y := 100000;
 
PL/SQL 
procedure 
successfully completed.
 
scott@ORCL>explain plan 
for 
select 
count
(*) 
from 
t1 
where 
object_id 
between 
:x 
and 
:y;
 
Explained.
 
scott@ORCL>
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 |    434 |  2170 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------
 
Predicate Information (identified 
by 
operation id):
---------------------------------------------------
 
   
2 - filter(TO_NUMBER(:Y)>=TO_NUMBER(:X))
   
3 - access(
"OBJECT_ID"
>=TO_NUMBER(:X) 
AND 
"OBJECT_ID"
<=TO_NUMBER(:Y))
 
16 
rows 
selected.
 
scott@ORCL>
select 
count
(*) 
from 
t1 
where 
object_id 
between 
:x 
and 
:y;
 
  
COUNT
(*)
----------
    
173380
 
scott@ORCL>
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    
|
---------------------------------------------------------------------------------
|   0 | 
SELECT 
STATEMENT       |   |   |   |   107 (100)|      |
|   1 |  SORT AGGREGATE        | |     1 |     5 |        |     |
|*  2 |   FILTER         | |   |   |        |     |
|*  3 |    
INDEX 
FAST 
FULL 
SCAN| IDX_T1 |   172K|   843K|   107   (1)| 00:00:02 |
---------------------------------------------------------------------------------
 
......省略部分输出
 
scott@ORCL>
set 
autotrace traceonly
scott@ORCL>
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 |    434 |  2170 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------

从上面显示内容可以看到,使用SET AUTOTRACE ON得到的执行计划和之前explain plan得到的执行计划也是一模一样的,即此时使用SET AUTOTRACE ON所得到的执行计划也是不准的。

另外,如果目标SQL的执行计划已经被age outShared Pool了,此时如何得到SQL的真实执行计划呢?

  • 如果是Oracle 10g 及其以上版本,该SQL的执行计划已经被Oracle捕获并存储到了AWR Repository中,则可以使用AWR SQL报告来得到真实的历史执行计划。

  • 如果是Oracle 9i,通常情况下已经没有办法再得到该SQL的执行计划,除非额外部署了Statspack报告,并且采集Statspack报告的level值大于或等于6

使用AWR SQL报告来得到真实的历史执行计划参考:http://hbxztc.blog.51cto.com/1587495/1897981

参考《基于Oracle的SQL优化》

     本文转自hbxztc 51CTO博客,原文链接:http://blog.51cto.com/hbxztc/1899175,如需转载请自行联系原作者

你可能感兴趣的文章
【转】Android布局优化之ViewStub
查看>>
网络安全管理技术作业-SNMP实验报告
查看>>
根据Uri获取文件的绝对路径
查看>>
Flutter 插件开发:以微信SDK为例
查看>>
.NET[C#]中NullReferenceException(未将对象引用到实例)是什么问题?如何修复处理?...
查看>>
边缘控制平面Ambassador全解读
查看>>
Windows Phone 7 利用计时器DispatcherTimer创建时钟
查看>>
程序员最喜爱的12个Android应用开发框架二(转)
查看>>
vim学习与理解
查看>>
DIRECTSHOW在VS2005中PVOID64问题和配置问题
查看>>
MapReduce的模式,算法以及用例
查看>>
《Advanced Linux Programming》读书笔记(1)
查看>>
zabbix agent item
查看>>
一步一步学习SignalR进行实时通信_7_非代理
查看>>
字符设备与块设备的区别
查看>>
为什么我弃用GNOME转向KDE(2)
查看>>
Redis学习记录初篇
查看>>
爬虫案例若干-爬取CSDN博文,糗事百科段子以及淘宝的图片
查看>>
Web实时通信技术
查看>>
第三章 计算机及服务器硬件组成结合企业运维场景 总结
查看>>