绑定变量的弱点——《Oracle高效设计》学习笔记

绑定变量虽然有很多优点,但在某些情况下不可以使用绑定变量,

 

比如,对于被绑定的字段的值,如果对于不同的值,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在第一次查询时,会通过绑定变量窥视,确定使用何种查询计划,

 

以后就使用完全相同的查询计划,不再考虑因不同的输入值而更新查询计划,这样做在有些情况下会导致数据库

 

执行错误的查询计划。

 

因此,对于这种情况,正确的做法是不使用绑定变量。

 

 

你可能感兴趣的:(绑定变量的弱点——《Oracle高效设计》学习笔记)