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

    技术2022-05-13  19

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

     

    比如,对于被绑定的字段的值,如果对于不同的值,Oracle应该使用不同的查询计划,这种情况下就不应该使用绑定变量。

     

     

    以下的例子说明了这个问题:

     

    create table records_to_be_processedasselect 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 statisticsfor tablefor all indexesfor 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           0Execute      1      0.00       0.00          0          0          0           0Fetch       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: 1Optimizer mode: ALL_ROWSParsing 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           0Execute      1      0.00       0.00          0          0          0           0Fetch     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: 0Optimizer mode: ALL_ROWSParsing 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           0Execute      1      0.00       0.00          0          0          0           0Fetch     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: 1Optimizer mode: ALL_ROWSParsing 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           0Execute      1      0.00       0.00          0          0          0           0Fetch       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: 0Optimizer mode: ALL_ROWSParsing 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在第一次查询时,会通过绑定变量窥视,确定使用何种查询计划,

     

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

     

    执行错误的查询计划。

     

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

     

     


    最新回复(0)