修改统计信息值恢复Oracle执行计划

经常会遇到由于日期字段统计信息的边界值不准确,导致Oracle SQL执行计划发生改变,通常是最大值没有及时更新或者最大值过大。

下面是遇到的一个案例,SQL的执行计划突然改变,原先使用的是index range scan,突然变成了index full scan。 导致SQL语句非常缓慢。


点击(此处)折叠或打开

  1. select count(*) from prd_t1 where input_date>trunc(sysdate-1)
  2. and input_date

原来的执行计划:

点击(此处)折叠或打开

  1. SQL> select count(*) from prd_t1 where input_date > trunc(sysdate);

  2.   COUNT(*)
  3. ----------

  4.     193311

  5. Execution Plan
  6. ----------------------------------------------------------

  7.    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=8)
  8.    1 0 SORT (AGGREGATE)
  9.    2 1 INDEX (RANGE SCAN) OF 'IDX_PRD_T1' (NON-UNIQU
  10.           E) (Cost=4 Card=2 Bytes=16)

变差的执行计划:


点击(此处)折叠或打开

  1. SQL> select count(*) from prd_t1 where input_date > trunc(sysdate);

  2.   COUNT(*)
  3. ----------

  4.     193311

  5. Execution Plan
  6. ----------------------------------------------------------

  7.    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=8)
  8.    1 0 SORT (AGGREGATE)
  9.    2 1 INDEX (FAST FULL SCAN) OF 'IDX_PRD_T1' (NON-UNIQU
  10.           E) (Cost=6458 Card=6130163 Bytes=49041304)

检查和字段的统计信息有关系,字段input_date的最小值和最大值分别是18-JAN-2016和15-MAY-2026。所以选择了fast full scan。

修改完最大值和最小值,执行计划恢复成使用rang scan


点击(此处)折叠或打开

  1. SQL> select table_name,TO_CHAR(TO_DATE(TRUNC(ENDPOINT_VALUE),'J'),'DD-MON-YYYY')
  2.   2 from dba_tab_histograms where table_name='PRD_T1' and column_name='INPUT_DATE';

  3. TABLE_NAME TO_CHAR(TO_DATE(TRUNC(ENDPOINT
  4. ------------------------------ ------------------------------

  5. PRD_T1 19-APR-2016
  6. PRD_T1 18-APR-2017

具体方法如下:



点击(此处)折叠或打开

  1. DECLARE
  2.    srec DBMS_STATS.STATREC;
  3.    v_distcnt NUMBER;
  4.    v_density NUMBER;
  5.    v_nullcnt NUMBER;
  6.    v_avgclen NUMBER;
  7.    numvals DBMS_STATS.NUMARRAY;
  8.    charvals DBMS_STATS.CHARARRAY;
  9.    datevals DBMS_STATS.DATEARRAY;
  10. BEGIN
  11.    -- Date Type


  12.    DBMS_STATS.get_column_stats (ownname => 'DBO',
  13.                                 tabname => 'PRD_T1',
  14.                                 colname => 'INPUT_DATE',
  15.                                 distcnt => v_distcnt,
  16.                                 density => v_density,
  17.                                 nullcnt => v_nullcnt,
  18.                                 srec => srec,
  19.                                 avgclen => v_avgclen
  20.                                );
  21.    datevals := DBMS_STATS.datearray (sysdate-365, sysdate);
  22.    DBMS_STATS.prepare_column_values (srec, datevals);
  23.        DBMS_STATS.set_column_stats (ownname => 'DBO',
  24.                                 tabname => 'PRD_T1',
  25.                                 colname => 'INPUT_DATE',
  26.                                 distcnt => v_distcnt,
  27.                                 density => v_density,
  28.                                 nullcnt => v_nullcnt,
  29.                                 srec => srec,
  30.                                 avgclen => v_avgclen
  31.                                );
  32.    COMMIT;
  33. END;
  34. /

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25105315/viewspace-2132015/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/25105315/viewspace-2132015/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值