cursor_sharing为force时带来的一个执行计划的假象

有时候可能存在评估的执行计划和真实的执行计划不一样,查看执行计划的方法如下:
a.explain plan ,可通过dbms_xplan.display来查看执行计划
b.set autot
c.v$sql_plan
d.dbms_xplan.display_cursor

a,b的执行计划都是根据explain plan得到的,因此都不是真实的(基表是sql_plan),而3,4的执行计划都是真实的(基表是 V$SQL_PLAN),cursor_sharing为force+直方图的时候可能存在一个假象,就是set autot trace给你显示的执行计划很完美,而真实的执行计划是当作绑定变量处理的,第一次查询的时候可能存在bind peeking的影响,而之后的如果没有新的cursor产生,那么执行计划都是重用第一次的,[@more@]

做了个测试如下:


SQL> conn l5m/l5m @dev107_c203
Connected.
SQL> show parameter cursor

NAME TYPE
------------------------------------ ---------------------------------
VALUE
------------------------------
cursor_sharing string
EXACT
cursor_space_for_time boolean
FALSE
open_cursors integer
500
session_cached_cursors integer
20
SQL> alter session set cursor_sharing=force;

Session altered.

SQL> create table kk1(id int);

Table created.

SQL> insert into kk1 select 1 from dual;

1 row created.

SQL> insert into kk1 select 2 from dba_objects;

63413 rows created.

SQL> create index i_kk1_1 on kk1(id);

Index created.

SQL> exec dbms_stats.gather_table_stats(user,'KK1',method_opt=>'for all columns size 254');

PL/SQL procedure successfully completed.

SQL> set autot trace
SQL> select count(*) from kk1 where id=1;


Execution Plan
----------------------------------------------------------
Plan hash value: 1026585023

-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | INDEX RANGE SCAN| I_KK1_1 | 1 | 3 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------

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

2 - access("ID"=1)


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
335 bytes sent via SQL*Net to client
377 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed


SQL> /


Execution Plan
----------------------------------------------------------
Plan hash value: 1026585023

-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | INDEX RANGE SCAN| I_KK1_1 | 1 | 3 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------

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

2 - access("ID"=1)


Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
335 bytes sent via SQL*Net to client
377 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed


SQL> select count(*) from kk1 where id=2;
//这里显示的执行计划是假的,真正的执行计划是index range scan


Execution Plan
----------------------------------------------------------
Plan hash value: 1408337260

---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 26 (8)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | TABLE ACCESS FULL| KK1 | 62313 | 182K| 26 (8)| 00:00:01 |
---------------------------------------------------------------------------

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

2 - filter("ID"=2)


Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
125 consistent gets
0 physical reads
0 redo size
337 bytes sent via SQL*Net to client
377 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

下面的真正的执行计划
SQL> set autot off
SQL> select sql_text,sql_id,child_number from v$sql
2 where sql_text like 'select count(*) from kk1%';

SQL_TEXT
--------------------------------------------------------------------------------
SQL_ID CHILD_NUMBER
--------------------------------------- ------------
select count(*) from kk1 where id=:"SYS_B_0"
1fnfa7pqtz9h6 0


SQL> select * from table(dbms_xplan.display_cursor('1fnfa7pqtz9h6','0'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID 1fnfa7pqtz9h6, child number 0
-------------------------------------
select count(*) from kk1 where id=:"SYS_B_0"

Plan hash value: 1026585023

-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 (100)| |
| 1 | SORT AGGREGATE | | 1 | 3 | | |

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
|* 2 | INDEX RANGE SCAN| I_KK1_1 | 1 | 3 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------

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

2 - access("ID"=:SYS_B_0)


19 rows selected.



SQL> set autot trace

可以发现下面的执行计划是假的,和加index(t)的提示的consistent gets是一致的
SQL> select count(*) from kk1 where id=2; //走索引逻辑读125


Execution Plan
----------------------------------------------------------
Plan hash value: 1408337260

---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 26 (8)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | TABLE ACCESS FULL| KK1 | 62313 | 182K| 26 (8)| 00:00:01 |
---------------------------------------------------------------------------

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

2 - filter("ID"=2)


Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
125 consistent gets
0 physical reads
0 redo size
337 bytes sent via SQL*Net to client
377 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed



SQL> select /*+ index(t) */ count(*) from kk1 t where id=2;


Execution Plan
----------------------------------------------------------
Plan hash value: 1026585023

-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 126 (2)| 00:00:02 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | INDEX RANGE SCAN| I_KK1_1 | 62313 | 182K| 126 (2)| 00:00:02 |
-----------------------------------------------------------------------------

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

2 - access("ID"=2)


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
125 consistent gets
0 physical reads
0 redo size
337 bytes sent via SQL*Net to client
377 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed



SQL> select /*+ full(t) */ count(*) from kk1 t where id=2;
//全表逻辑读107


Execution Plan
----------------------------------------------------------
Plan hash value: 1408337260

---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 26 (8)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | TABLE ACCESS FULL| KK1 | 62313 | 182K| 26 (8)| 00:00:01 |
---------------------------------------------------------------------------

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

2 - filter("ID"=2)


Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
107 consistent gets
0 physical reads
0 redo size
337 bytes sent via SQL*Net to client
377 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed



下面看看dbms_xplan.display与dbms_xplan.display_cursor两个包的结果是否一致

SQL> explain plan set statement_id='NO' for
2 select count(*) from kk1 where id=2;

SQL> select plan_table_output
2 from table(dbms_xplan.display('PLAN_TABLE','NO','ALL'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1408337260

---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 26 (8)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | TABLE ACCESS FULL| KK1 | 62313 | 182K| 26 (8)| 00:00:01 |
---------------------------------------------------------------------------

Query Block Name / Object Alias (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
-------------------------------------------------------------

1 - SEL$1
2 - SEL$1 / KK1@SEL$1

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

2 - filter("ID"=2)

Column Projection Information (identified by operation id):

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
-----------------------------------------------------------

1 - (#keys=0) COUNT(*)[22]

25 rows selected.




SQL> select sql_text,sql_id,child_number from v$sql where sql_text like 'select count(*) from kk1%';


SQL_TEXT
--------------------------------------------------------------------------------
SQL_ID CHILD_NUMBER
--------------------------------------- ------------
select count(*) from kk1 where id=:"SYS_B_0"
1fnfa7pqtz9h6 0


SQL> select * from table(dbms_xplan.display_cursor('1fnfa7pqtz9h6','0'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID 1fnfa7pqtz9h6, child number 0
-------------------------------------
select count(*) from kk1 where id=:"SYS_B_0"

Plan hash value: 1026585023

-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 (100)| |
| 1 | SORT AGGREGATE | | 1 | 3 | | |

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
|* 2 | INDEX RANGE SCAN| I_KK1_1 | 1 | 3 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------

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

2 - access("ID"=:SYS_B_0)


19 rows selected.


由于dbms_xplan.display表的基表是plan_table,而dbms_xplan.display_cursor的基表是v$sql_plan,看出结果是不一致的。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/271283/viewspace-1020411/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/271283/viewspace-1020411/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值