Oracle开发者性能课第1课(如何阅读执行计划)实验
Posted dingdingfish
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle开发者性能课第1课(如何阅读执行计划)实验相关的知识,希望对你有一定的参考价值。
概述
本实验参考DevGym中的实验指南。
创建环境
首先创建表,并在最后搜集统计信息:
create table bricks (
colour varchar2(10),
shape varchar2(10)
);
create table colours (
colour varchar2(10),
rgb_hex_value varchar2(6)
);
create table cuddly_toys (
toy_name varchar2(20),
colour varchar2(10)
);
create table pens (
colour varchar2(10),
pen_type varchar2(10)
);
insert into cuddly_toys values ( 'Miss Snuggles', 'pink' ) ;
insert into cuddly_toys values ( 'Cuteasaurus', 'blue' ) ;
insert into cuddly_toys values ( 'Baby Turtle', 'green' ) ;
insert into cuddly_toys values ( 'Green Rabbit', 'green' ) ;
insert into cuddly_toys values ( 'White Rabbit', 'white' ) ;
insert into colours values ( 'red' , 'FF0000' );
insert into colours values ( 'blue' , '0000FF' );
insert into colours values ( 'green' , '00FF00' );
insert into bricks values ( 'red', 'cylinder' );
insert into bricks values ( 'blue', 'cube' );
insert into bricks values ( 'green', 'cube' );
insert into bricks
select * from bricks;
insert into bricks
select * from bricks;
insert into bricks
select * from bricks;
insert into pens values ( 'black', 'ball point' );
insert into pens values ( 'black', 'permanent' );
insert into pens values ( 'blue', 'ball point' );
insert into pens values ( 'green', 'permanent' );
insert into pens values ( 'green', 'dry-wipe' );
insert into pens values ( 'red', 'permanent' );
insert into pens values ( 'red', 'dry-wipe' );
insert into pens values ( 'blue', 'permanent' );
insert into pens values ( 'blue', 'dry-wipe' );
commit;
exec dbms_stats.gather_table_stats ( null, 'pens' ) ;
exec dbms_stats.gather_table_stats ( null, 'colours' ) ;
exec dbms_stats.gather_table_stats ( null, 'bricks' ) ;
exec dbms_stats.gather_table_stats ( null, 'cuddly_toys' ) ;
查看数据,总共4个表:
SQL> select * from bricks;
COLOUR SHAPE
_________ ___________
red cylinder
blue cube
green cube
red cylinder
blue cube
green cube
red cylinder
blue cube
green cube
red cylinder
blue cube
green cube
red cylinder
blue cube
green cube
red cylinder
blue cube
green cube
red cylinder
blue cube
green cube
red cylinder
blue cube
green cube
24 rows selected.
SQL> select * from colours;
COLOUR RGB_HEX_VALUE
_________ ________________
red FF0000
blue 0000FF
green 00FF00
SQL> select * from cuddly_toys;
TOY_NAME COLOUR
________________ _________
Miss Snuggles pink
Cuteasaurus blue
Baby Turtle green
Green Rabbit green
White Rabbit white
SQL> select * from pens;
COLOUR PEN_TYPE
_________ _____________
black ball point
black permanent
blue ball point
green permanent
green dry-wipe
red permanent
red dry-wipe
blue permanent
blue dry-wipe
9 rows selected.
DBMS_XPLAN获取执行计划
推荐看一下How to Create an Execution Plan
推荐方法是使用DBMS_XPLAN,下例是获取最近一个SQL的执行计划。
SQL> select *
2 from bricks b
3 join colours c
4 on b.colour = c.colour;
COLOUR SHAPE COLOUR RGB_HEX_VALUE
_________ ___________ _________ ________________
red cylinder red FF0000
blue cube blue 0000FF
green cube green 00FF00
red cylinder red FF0000
blue cube blue 0000FF
green cube green 00FF00
red cylinder red FF0000
blue cube blue 0000FF
green cube green 00FF00
red cylinder red FF0000
blue cube blue 0000FF
green cube green 00FF00
red cylinder red FF0000
blue cube blue 0000FF
green cube green 00FF00
red cylinder red FF0000
blue cube blue 0000FF
green cube green 00FF00
red cylinder red FF0000
blue cube blue 0000FF
green cube green 00FF00
red cylinder red FF0000
blue cube blue 0000FF
green cube green 00FF00
24 rows selected.
SQL> select * from table(dbms_xplan.display_cursor());
PLAN_TABLE_OUTPUT
_________________________________________________________________________________
SQL_ID bhrapfvbrag71, child number 0
-------------------------------------
select * from bricks b join colours c on b.colour = c.colour
Plan hash value: 2784388402
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 6 (100)| |
|* 1 | HASH JOIN | | 24 | 552 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| COLOURS | 3 | 36 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| BRICKS | 24 | 264 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("B"."COLOUR"="C"."COLOUR")
20 rows selected.
查找SQL语句的SQL ID
SQL_ID为13字节,是SQL文本的哈希值。所以SQL不变,SQL_ID不变;哪怕SQL中加入了注释,SQL_ID也会变。
SQL> select sql_id, sql_text
2 from v$sql
3 where sql_text like 'select *%bricks b%'
4 ;
SQL_ID SQL_TEXT
________________ _______________________________________________________________________
bhrapfvbrag71 select * from bricks b join colours c on b.colour = c.colour
在DBMS_XPLAN中使用SQL_ID
这样就可以查看其它会话或之前的SQL的执行计划:
SQL> select *
2 from table(dbms_xplan.display_cursor('bhrapfvbrag71'));
PLAN_TABLE_OUTPUT
_________________________________________________________________________________
SQL_ID bhrapfvbrag71, child number 0
-------------------------------------
select * from bricks b join colours c on b.colour = c.colour
Plan hash value: 2784388402
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 6 (100)| |
|* 1 | HASH JOIN | | 24 | 552 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| COLOURS | 3 | 36 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| BRICKS | 24 | 264 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("B"."COLOUR"="C"."COLOUR")
20 rows selected.
如果不知道SQL_ID,也可以通过SQL文本查找:
select /* colours query */* from colours;
select p.*
from v$sql s, table (
dbms_xplan.display_cursor (
s.sql_id, s.child_number, 'BASIC'
)
) p
where s.sql_text like '%colours query%' /* enter text from the target statement here */
and s.sql_text not like '%not this%';
如何阅读执行计划
不赘述了,推荐How to Read an Execution Plan
核心规则就是:
To follow an execution plan, the database uses a depth-first search, which starts from the top of the plan and works down the tree to the first leaf. It then walks back up the tree to the first operation with an unvisited child.
使用深度优先搜索,从执行计划的顶部开始,沿着树一直向下搜索到第一个叶子节点。 然后回到父节点下面下一个未访问过的子节点。
执行计划解读示例1
select c.*, pen_type, shape, toy_name
from colours c
join pens p
on c.colour = p.colour
join cuddly_toys t
on c.colour = t.colour
join bricks b
on c.colour = b.colour;
select *
from table(dbms_xplan.display_cursor());
PLAN_TABLE_OUTPUT
_______________________________________________________________________________________
SQL_ID gdk2sd4huxr83, child number 0
-------------------------------------
select c.*, pen_type, shape, toy_name from colours c join pens p
on c.colour = p.colour join cuddly_toys t on c.colour =
t.colour join bricks b on c.colour = b.colour
Plan hash value: 1245878025
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 12 (100)| |
|* 1 | HASH JOIN | | 68 | 3876 | 12 (0)| 00:00:01 |
|* 2 | HASH JOIN | | 8 | 368 | 9 (0)| 00:00:01 |
|* 3 | HASH JOIN | | 4 | 124 | 6 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| COLOURS | 3 | 36 | 3 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL| CUDDLY_TOYS | 5 | 95 | 3 (0)| 00:00:01 |
| 6 | TABLE ACCESS FULL | PENS | 9 | 135 | 3 (0)| 00:00:01 |
| 7 | TABLE ACCESS FULL | BRICKS | 24 | 264 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("C"."COLOUR"="B"."COLOUR")
2 - access("C"."COLOUR"="P"."COLOUR")
3 - access("C"."COLOUR"="T"."COLOUR")
28 rows selected.
执行顺序为:4,3,5,3,2,6,2,1,7,1,0。
执行计划解读示例2
select c.colour, count(*)
from colours c
join (
select colour, shape from bricks
union all
select colour, toy_name from cuddly_toys
union all
select colour, pen_type from pens
) t
on t.colour = c.colour
group by c.colour;
select *
from table(dbms_xplan.display_cursor());
PLAN_TABLE_OUTPUT
________________________________________________________________________________________
SQL_ID 2c2x0ux1k106c, child number 0
-------------------------------------
select c.colour, count(*) from colours c join ( select colour,
shape from bricks union all select colour, toy_name from
cuddly_toys union all select colour, pen_type from pens ) t on
t.colour = c.colour group by c.colour
Plan hash value: 1792629648
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 13 (100)| |
| 1 | HASH GROUP BY | | 3 | 33 | 13 (8)| 00:00:01 |
|* 2 | HASH JOIN | | 23 | 253 | 12 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL | COLOURS | 3 | 15 | 3 (0)| 00:00:01 |
| 4 | VIEW | | 38 | 228 | 9 (0)| 00:00:01 |
| 5 | UNION-ALL | | | | | |
| 6 | TABLE ACCESS FULL| BRICKS | 24 | 120 | 3 (0)| 00:00:01 |
| 7 | TABLE ACCESS FULL| CUDDLY_TOYS | 5 | 30 | 3 (0)| 00:00:01 |
| 8 | TABLE ACCESS FULL| PENS | 9 | 54 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T"."COLOUR"="C"."COLOUR")
28 rows selected.
执行顺序为:3,2,6,7,8,5,2,1,0
查看执行计划中处理的行数
通过format参数可指定许多选项。
select *
from bricks b
join colours c
on b.colour = c.colour;
select *
from table(dbms_xplan.display_cursor(:LIVESQL_LAST_SQL_ID, format => 'ROWSTATS LAST'));
PLAN_TABLE_OUTPUT
_______________________________________________________________________
SQL_ID bhrapfvbrag71, child number 1
-------------------------------------
select * from bricks b join colours c on b.colour = c.colour
Plan hash value: 2784388402
-----------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows |
-----------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 24 |
|* 1 | HASH JOIN | | 1 | 24 | 24 |
| 2 | TABLE ACCESS FULL| COLOURS | 1 | 3 | 3 |
| 3 | TABLE ACCESS FULL| BRICKS | 1 | 24 | 24 |
-----------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("B"."COLOUR"="C"."COLOUR")
20 rows selected.
要获得基本执行计划之外的统计信息,需要以下两个条件之一:
- SQL中有提示/*+ gather_plan_statistics */
- alter session set statistics_level = all
否则会有如下的警告,并且有信息缺失:
PLAN_TABLE_OUTPUT
____________________________________________________________________________________
SQL_ID bhrapfvbrag71, child number 0
-------------------------------------
以上是关于Oracle开发者性能课第1课(如何阅读执行计划)实验的主要内容,如果未能解决你的问题,请参考以下文章