Oracle通过10053分析"谓词越界"引起执行计划不准确

ORACLE , 通过10053分析"谓词越界"引起执行计划不准确

有客户问起在看10053 trace时 其中的
Using prorated density : xxx as selectivity of out-of-range value pred 这句怎么理解.

Oracle通过10053分析
IMG_5769.PNG

简单说: 发现谓词越界, cost为估算;
即: 在优化器尝试计算COST时,发现where条件中某列给定的值不在 统计信息中记录的值范围内(dba_tab_col_statistics的low value和Highvalue之间), 因为只能估算cost. 这时就有可能出现偏差. 如果这个偏差很大,就会导到执行计划不准确;

做了个示例,来模拟"谓词越界"

---session A

SQL> create  table tbl_tst as select  * from dba_objects;


SQL> create index idx_tbl_tst on tbl_tst (object_id);

Index created.

#这里删除柱状图(个人不喜欢直方图)
SQL> exec DBMS_STATS.DELETE_TABLE_STATS(TABNAME=>'TBL_TST',ownname=>'JASON',no_invalidate=>FALSE,cascade_indexes=>TRUE,cascade_parts=>TRUE) ;

#重新收集统计信息
SQL> exec DBMS_STATS.GATHER_TABLE_STATS(ownname=>'JASON',tabname=>'TBL_TST',estimate_percent=>0,method_opt=>'FOR ALL COLUMNS SIZE 1',no_invalidate=>false,cascade=>true,degree => 10);

#表中object_id 的实际最大小值 
SQL> select min(object_id),max(object_id) from tbl_tst;

MIN(OBJECT_ID) MAX(OBJECT_ID)
-------------- --------------
             2          97632

#查看在统计信息中记录的OBJECT最大小值 
SQL> col COLUMN_NAME for a15
SQL> select COLUMN_NAME,UTL_RAW.CAST_TO_NUMBER(LOW_VALUE) MIN,UTL_RAW.CAST_TO_NUMBER(HIGH_VALUE) MAX,HISTOGRAM,num_buckets  from dba_tab_col_statistics cs
  2   where owner='JASON' AND table_name='TBL_TST' AND COLUMN_NAME='OBJECT_ID'; 

COLUMN_NAME            MIN        MAX HISTOGRAM                                     NUM_BUCKETS
--------------- ---------- ---------- --------------------------------------------- -----------
OBJECT_ID                2      97632 NONE                                                    1

SQL> 

SQL> select sid from v$mystat where rownum=1;

       SID
----------
       141

SQL> select spid from v$process where addr in (select paddr from v$session where sid=141);

SPID
------------------------------------------------------------------------
13964

--session B

SQL> conn / as sysdba
SQL> oradebug setospid 13964
Oracle pid: 19, Unix process pid: 13964, image: oracle@myzdb100 (TNS V1-V3)
SQL> oradebug tracefile_name
/u01/app/oracle/diag/rdbms/myzdb/myzdb/trace/myzdb_ora_13964.trc
SQL> oradebug event 10053 trace name context forever, level 1
Statement processed.
SQL> 

--session A

SQL> select  object_name from tbl_tst where object_id=99999;

no rows selected

--session B

SQL> oradebug event 10053 trace name context off
Statement processed.

vi /u01/app/oracle/diag/rdbms/myzdb/myzdb/trace/myzdb_ora_13964.trc
....
Access path analysis for TBL_TST
***************************************
SINGLE TABLE ACCESS PATH
  Single Table Cardinality Estimation for TBL_TST[TBL_TST]
  Column (#4): OBJECT_ID(
    AvgLen: 5 NDV: 87152 Nulls: 0 Density: 0.000011 Min: 2 Max: 97632
# NDV 即number of distinct values 
# Density 密度值,越低越好, 超过0.2 的话列上的索引意义不大了.
# 这里看到OBJECT_ID 最小2,最大97632,
  Using prorated density: 0.000011 of col #4 as selectvity of out-of-range/non-existent value pred
#这里看到发现 object_id=99999 超出了 统计信息中的值,按照0.000011 的密度值来计算cost
  Table: TBL_TST  Alias: TBL_TST
    Card: Original: 87152.000000  Rounded: 1  Computed: 0.98  Non Adjusted: 0.98
#计划1: 走全表, COST算下来346
  Access Path: TableScan
    Cost:  346.86  Resp: 346.86  Degree: 0
      Cost_io: 346.00  Cost_cpu: 31717992
      Resp_io: 346.00  Resp_cpu: 31717992
  Using prorated density: 0.000011 of col #4 as selectvity of out-of-range/non-existent value pred
#计划2: 走索引, COST算下来2
  Access Path: index (AllEqRange)
    Index: IDX_TBL_TST
    resc_io: 2.00  resc_cpu: 15503
    ix_sel: 0.000011  ix_sel_with_filters: 0.000011
    Cost: 2.00  Resp: 2.00  Degree: 1
#因此best计划选择 走索引
  Best:: AccessPath: IndexRange
  Index: IDX_TBL_TST
         Cost: 2.00  Degree: 1  Resp: 2.00  Card: 0.98  Bytes: 0

***************************************
....

可以看出 ,其实一般情况下, 即使越界了, 估算也是很准确的.

你可能感兴趣的:(Oracle通过10053分析"谓词越界"引起执行计划不准确)