绑定变量虽然有很多优点,但在某些情况下不可以使用绑定变量,
比如,对于被绑定的字段的值,如果对于不同的值,Oracle应该使用不同的查询计划,这种情况下就不应该使用绑定变量。
以下的例子说明了这个问题:
create table records_to_be_processed
as
select decode( mod(rownum,100), 0, 'N', 'Y' ) processed, a.*
from all_objects a;
create index processed_idx on records_to_be_processed(processed);
analyze table records_to_be_processed compute statistics
for table
for all indexes
for all indexed columns
/
Alter system flush shared_pool;
Alter session set sql_trace=true;
variable processed varchar2(1);
exec :processed := 'N';
select *
from records_to_be_processed initially_N
where processed = :processed;
exec :processed := 'Y';
select *
from records_to_be_processed initially_N
where processed = :processed;
exec :processed := 'Y';
select *
from records_to_be_processed initially_Y
where processed = :processed;
exec :processed := 'N';
select *
from records_to_be_processed initially_Y
where processed = :processed;
set autotrace off
tkprof的结果摘录如下(设置aggregate=no):
查询1:
select *
from records_to_be_processed initially_N
where processed = :processed
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 35 0.00 0.00 0 532 0 496
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 37 0.00 0.01 0 532 0 496
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 5
Rows Row Source Operation
------- ---------------------------------------------------
496 TABLE ACCESS BY INDEX ROWID RECORDS_TO_BE_PROCESSED (cr=532 pr=0 pw=0 time=9940 us)
496 INDEX RANGE SCAN PROCESSED_IDX (cr=36 pr=0 pw=0 time=4966 us)(object id 52912)
查询2:
select *
from records_to_be_processed initially_N
where processed = :processed
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 3279 0.20 0.27 0 7289 0 49157
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3281 0.20 0.27 0 7289 0 49157
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 5
Rows Row Source Operation
------- ---------------------------------------------------
49157 TABLE ACCESS BY INDEX ROWID RECORDS_TO_BE_PROCESSED (cr=7289 pr=0 pw=0 time=491723 us)
49157 INDEX RANGE SCAN PROCESSED_IDX (cr=3369 pr=0 pw=0 time=196654 us)(object id 52912)
查询3:
select *
from records_to_be_processed initially_Y
where processed = :processed
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 3279 0.21 0.21 0 3925 0 49157
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3281 0.21 0.21 0 3925 0 49157
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 5
Rows Row Source Operation
------- ---------------------------------------------------
49157 TABLE ACCESS FULL RECORDS_TO_BE_PROCESSED (cr=3925 pr=0 pw=0 time=196768 us)
查询4:
select *
from records_to_be_processed initially_Y
where processed = :processed
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 35 0.00 0.00 0 734 0 496
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 37 0.00 0.00 0 734 0 496
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 5
Rows Row Source Operation
------- ---------------------------------------------------
496 TABLE ACCESS FULL RECORDS_TO_BE_PROCESSED (cr=734 pr=0 pw=0 time=6489 us)
这个结果说明,如果使用了绑定变量,Oracle在第一次查询时,会通过绑定变量窥视,确定使用何种查询计划,
以后就使用完全相同的查询计划,不再考虑因不同的输入值而更新查询计划,这样做在有些情况下会导致数据库
执行错误的查询计划。
因此,对于这种情况,正确的做法是不使用绑定变量。