爲什麼會產生這種問題:在執行含有綁定變量的查詢語句時,完成解析和最優化操作之後對綁定變量進行綁定,這以爲着在實現最優化操作時無法使用綁定變量列的統計信息。爲了解決這個問題,數據庫使用了窺探技術,在第一次解析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)
http://blog.csdn.net/stevendbaguo/article/details/8175633