ly stat;
hr@ora11g > select * from t1 where id=:v_id;
hr@ora11g > select * from t1 where id=:v_id;
hr@ora11g > select * from t1 where id=:v_id;
注意:这里,我们之所以要多执行几次,主要是因为如果只是执行一次或两次,oracle能够认识到你传入的绑定变量落在了第一次的绑定变量(12462)所在的cube之外,但是oracle认为你可能只是偶尔执行该绑定变量,所以并不一定会使用另外那个全表扫描的执行计划。多执行几次以后,你会发现consistent gets突然从1390直线下降到了715,这时就说明oracle开始使用新的全表扫描的执行计划了。
然后,这时我们再去查看v$sql里该sql语句有几条记录。
hr@ora11g > select sql_text,sql_id,child_number,plan_hash_value
2 from v$sql where sql_text like 'select * from t1 where%';
SQL_TEXT SQL_ID CHILD_NUMBER PLAN_HASH_VALUE
--------------------------------- ------------- ------------ ----------------
select * from t1 where id=:v_id 7y7tt6xyhas1g 0 50753647
select * from t1 where id=:v_id 7y7tt6xyhas1g 1 3617692013
我们发现,该SQL语句在内存里存在两条记录了,也就是存在两个子游标了,分别对应了不同的执行计划。同样,我们来看一下新产生的子游标,也就是child_number为1的执行计划是怎样的。
SQL> select * from table(dbms_xplan.display_cursor('7y7tt6xyhas1g',1));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID 7y7tt6xyhas1g, child number 1
-------------------------------------
select * from t1 where id=:v_id
Plan hash value: 3617692013
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 16 (100) | |
|* 1 | TABLE ACCESS FULL| T1 | 9974 | 204K | 16 (0) | 00:00:01 |
......
我们还可以从另外的角度来验证11g里的动态绑定变量窥视,也就是设置sql_trace的方式。这个方式比较简单,只要先发出:alter session set sql_trace=true以后,传入两个不同的绑定变量,然后分别就不同的绑定变量多执行几次。最后调用tkprof对跟踪文件进行分析。这里注意两个地方,第一是跟踪文件位于ADR中,不再位于user_dump_dest参数所指定的目录里了。就这里的跟踪文件而言,其所在位置缺省为:$ORACLE_HOME/diag/rdbms///trace目录下;第二个要注意的是使用tkprof时,添加aggregate=no选项,缺省会将相同SQL语句合并,这样你就发现不到对于相同SQL语句的不同的执行计划了。
这里节选部分使用tkprof得到的文件内容,如下所示。
......
SQL ID : 7y7tt6xyhas1g
select *
from
t1 where id=:v_id
......
Rows Row Source Operation
------- ---------------------------------------------------
10000 TABLE ACCESS BY INDEX ROWID T1 (cr=1390 pr=0 pw=0 time=446 us cost=2 size=21 card=1)
10000 INDEX RANGE SCAN IDX_T1 (cr=687 pr=0 pw=0 time=228 us cost=1 size=0 card=1)(object id 12463)
......
SQL ID : 7y7tt6xyhas1g
select *
from
t1 where id=:v_id
......
Rows Row Source Operation
------- ---------------------------------------------------
10000 TABLE ACCESS FULL T1 (cr=715 pr=0 pw=0 time=142 us cost=16 size=209454 card=9974)
......
从这里也可以很清楚的看到,对于不同的绑定变量,oracle能够自行选择是否应该生成更好的执行计划并使用该执行计划。