绑定变量窥探(bind peeking)--什么使执行计划不准
2012-11-12 19:12
639 查看
OLTP中为了解决SQL语句硬解析的问题,使用了绑定变量,在oracle 10g版本中,这样带来一个问题,每次SQL的执行计划可能不是最优的,正式环境和测试环境上的执行计划不一致。
为什么会产生这种问题:在执行含有绑定变量的查询语句时,完成解析和最优化操作之后对绑定变量进行绑定,这以为着在实现最优化操作时无法使用绑定变量列的统计信息。为了解决这个问题,数据库使用了窥探技术,在第一次解析SQL时,按照窥探变量的值生成执行计划,以后这样的SQL都按照这个执行。隐藏参数_optim_peek_user_binds=true则启用绑定变量窥探,否则CBO认为统计列是均匀的。下面来做个实验,注意的是
set autotrace这个玩意产生的执行计划可能不准:
SQL> create table test as select * from all_objects;
SQL> create index ind_object_name on TEST (object_name);
SQL> exec dbms_stats.gather_table_stats(user,'TEST',cascade=>true);
SQL> update test set object_name='aaa';
SQL> commit;
SQL> update test set object_name='bbb' where object_id=20;
SQL> commit;
SQL> select count(1) from test where object_name='aaa';
COUNT(1)
----------
50653
SQL> select count(1) from test where object_name='bbb';
COUNT(1)
----------
1
SQL> var ccc varchar2(10);
SQL> exec :ccc:='aaa';--按道理说是全表扫描,结果也是全表扫描
SQL> set autotrace exp
SQL> select * from test where object_name=:ccc;
SQL> set autotrace off;
SQL> select hash_value, child_number
2 from v$sql
3 where sql_text = 'select * from test where object_name=:ccc';
HASH_VALUE CHILD_NUMBER
---------- ------------
2373399249
0
SQL> select * from table(dbms_xplan.display_cursor(2373399249,0));
| Id
| Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
|
0 | SELECT STATEMENT | | | | 163 (100)| |
|* 1 | TABLE ACCESS FULL| TEST | 50654 | 3611K| 163 (4)| 00:00:02 |
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_NAME"=:CCC)
---------------------------------------------------------------------------------------------------------------------
SQL> exec :ccc:='bbb';--按道理说是索引扫描,但是结果却是全表扫描
SQL> set autotrace exp
SQL> select * from test where object_name=:ccc;
SQL> set autotrace off;
SQL> select hash_value, child_number
2 from v$sql
3 where sql_text = 'select * from test where object_name=:ccc';
HASH_VALUE CHILD_NUMBER
---------- ------------
2373399249
0
SQL> select * from table(dbms_xplan.display_cursor(2373399249,0));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
| Id
| Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
|
0 | SELECT STATEMENT | | | | 163 (100)| |
|* 1 | TABLE ACCESS FULL| TEST | 50654 | 3611K| 163 (4)| 00:00:02 |
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_NAME"=:CCC)
SQL> alter system flush shared_pool;--清理share_pool
SQL> exec :ccc:='bbb';--按道理说是索引扫描,结果也是索引扫描
SQL> set autotrace exp
SQL> select * from test where object_name=:ccc;
SQL> select hash_value, child_number
2 from v$sql
3 where sql_text = 'select * from test where object_name=:ccc';
HASH_VALUE CHILD_NUMBER
---------- ------------
2373399249
0
SQL> select * from table(dbms_xplan.display_cursor(2373399249,0));
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------
| Id
| Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 73 | 2 (0)| 00:00:01 |
|*
2 | INDEX RANGE SCAN | IND_OBJECT_NAME | 1 | |1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_NAME"=:CCC)
SQL> exec :ccc:='aaa';--按道理说是全表扫描,但结果却是索引扫描
SQL> select * from test where object_name=:ccc;
SQL> select hash_value, child_number
2 from v$sql
3 where sql_text = 'select * from test where object_name=:ccc';
HASH_VALUE CHILD_NUMBER
---------- ------------
2373399249
0
SQL> select * from table(dbms_xplan.display_cursor(2373399249,0));
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------
| Id
| Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
|
0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 73 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IND_OBJECT_NAME | 1 | |1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_NAME"=:CCC)
为什么会产生这种问题:在执行含有绑定变量的查询语句时,完成解析和最优化操作之后对绑定变量进行绑定,这以为着在实现最优化操作时无法使用绑定变量列的统计信息。为了解决这个问题,数据库使用了窥探技术,在第一次解析SQL时,按照窥探变量的值生成执行计划,以后这样的SQL都按照这个执行。隐藏参数_optim_peek_user_binds=true则启用绑定变量窥探,否则CBO认为统计列是均匀的。下面来做个实验,注意的是
set autotrace这个玩意产生的执行计划可能不准:
SQL> create table test as select * from all_objects;
SQL> create index ind_object_name on TEST (object_name);
SQL> exec dbms_stats.gather_table_stats(user,'TEST',cascade=>true);
SQL> update test set object_name='aaa';
SQL> commit;
SQL> update test set object_name='bbb' where object_id=20;
SQL> commit;
SQL> select count(1) from test where object_name='aaa';
COUNT(1)
----------
50653
SQL> select count(1) from test where object_name='bbb';
COUNT(1)
----------
1
SQL> var ccc varchar2(10);
SQL> exec :ccc:='aaa';--按道理说是全表扫描,结果也是全表扫描
SQL> set autotrace exp
SQL> select * from test where object_name=:ccc;
SQL> set autotrace off;
SQL> select hash_value, child_number
2 from v$sql
3 where sql_text = 'select * from test where object_name=:ccc';
HASH_VALUE CHILD_NUMBER
---------- ------------
2373399249
0
SQL> select * from table(dbms_xplan.display_cursor(2373399249,0));
| Id
| Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
|
0 | SELECT STATEMENT | | | | 163 (100)| |
|* 1 | TABLE ACCESS FULL| TEST | 50654 | 3611K| 163 (4)| 00:00:02 |
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_NAME"=:CCC)
---------------------------------------------------------------------------------------------------------------------
SQL> exec :ccc:='bbb';--按道理说是索引扫描,但是结果却是全表扫描
SQL> set autotrace exp
SQL> select * from test where object_name=:ccc;
SQL> set autotrace off;
SQL> select hash_value, child_number
2 from v$sql
3 where sql_text = 'select * from test where object_name=:ccc';
HASH_VALUE CHILD_NUMBER
---------- ------------
2373399249
0
SQL> select * from table(dbms_xplan.display_cursor(2373399249,0));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
| Id
| Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
|
0 | SELECT STATEMENT | | | | 163 (100)| |
|* 1 | TABLE ACCESS FULL| TEST | 50654 | 3611K| 163 (4)| 00:00:02 |
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OBJECT_NAME"=:CCC)
SQL> alter system flush shared_pool;--清理share_pool
SQL> exec :ccc:='bbb';--按道理说是索引扫描,结果也是索引扫描
SQL> set autotrace exp
SQL> select * from test where object_name=:ccc;
SQL> select hash_value, child_number
2 from v$sql
3 where sql_text = 'select * from test where object_name=:ccc';
HASH_VALUE CHILD_NUMBER
---------- ------------
2373399249
0
SQL> select * from table(dbms_xplan.display_cursor(2373399249,0));
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------
| Id
| Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 73 | 2 (0)| 00:00:01 |
|*
2 | INDEX RANGE SCAN | IND_OBJECT_NAME | 1 | |1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_NAME"=:CCC)
SQL> exec :ccc:='aaa';--按道理说是全表扫描,但结果却是索引扫描
SQL> select * from test where object_name=:ccc;
SQL> select hash_value, child_number
2 from v$sql
3 where sql_text = 'select * from test where object_name=:ccc';
HASH_VALUE CHILD_NUMBER
---------- ------------
2373399249
0
SQL> select * from table(dbms_xplan.display_cursor(2373399249,0));
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------
| Id
| Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------
|
0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 73 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IND_OBJECT_NAME | 1 | |1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_NAME"=:CCC)
相关文章推荐
- 绑定变量窥探(bind peeking)--什么使执行计划不准
- Event 10053 执行计划 绑定变量 Bind peeking
- Event 10053 执行计划 绑定变量 Bind peeking
- 查看真实的执行计划 绑定变量对执行计划的影响--“绑定变量窥探”
- 一个执行计划异常变更的案例 - 外传之绑定变量窥探
- 如何解决绑定变量造成执行计划不准的问题?
- 构造绑定含有绑定变量的JAVA的SQL语句执行计划
- 通过重新生成执行计划解决绑定变量执行计划偏差导致SQL执行时间过长
- 柱状图(Histogram),绑定变量,bind peeking,cursor_sharing 之间的关系3 柱状图与cursor_sharing
- 柱状图(Histogram),绑定变量,bind peeking,cursor_sharing 之间的关系3 柱状图与cursor_sharing
- sql执行计划[Oracle] 变量绑定
- 绑定变量和BIND PEEKING
- Event 10053 执行计划 绑定变量
- 柱状图(Histogram),绑定变量,bind peeking,cursor_sharing 之间的关系2 绑定变量与柱状图
- autotrace显示绑定变量执行计划不准确
- 柱状图(Histogram),绑定变量,bind peeking,cursor_sharing 之间的关系2 绑定变量与柱状图
- Oracle:执行计划:访问路径、表连接、提示、统计信息、绑定变量
- 绑定变量导致执行计划不走索引
- 错误的转换绑定变量类型导致执行计划错误
- 什么是bind variable(绑定变量)?