当无统计信息的时候ix_sel的值取决于什么

| 1 Comment | No TrackBacks

在"利用10053分析执行计划的一个例子"这篇文章里,我提到----"这个默认值不是固定的,感觉这里这个默认值取决于Blks"。

 

当时为什么这么说是因为我看到的所有关于10053的文章中都或直接或隐约的指出当没有统计信息的时候,oracle是根据Blks来计算默认的统计信息。

 

呵呵,这个观点误导了我,我们来看一下真相是什么。

 

SQL> create table tb0624 (type number,ts timestamp) pctfree 90;

 

Table created

 

SQL> begin

  2  for i in 1..10000 loop

  3  insert into tb0624 values (1,sysdate);

  4  insert into tb0624 values (3,sysdate);

  5  end loop;

  6  commit;

  7  end;

  8  /

 

PL/SQL procedure successfully completed

 

SQL> begin

  2  for i in 1..10 loop

  3  insert into tb0624 values (2,sysdate);

  4  end loop;

  5  commit;

  6  end;

  7  /

 

PL/SQL procedure successfully completed

 

SQL> exec dbms_stats.gather_table_stats('IPRA','TB0624',CASCADE=>FALSE,METHOD_OPT => 'FOR ALL INDEXED COLUMNS')

 

PL/SQL procedure successfully completed

 

SQL> SELECT NUM_ROWS,BLOCKS,AVG_ROW_LEN FROM USER_TABLES WHERE TABLE_NAME='TB0624';

 

  NUM_ROWS     BLOCKS AVG_ROW_LEN

---------- ---------- -----------

     20010        438          14

 

SQL> create index idx_type on tb0624(type);

 

Index created

 

这里我们分别修改NUM_ROWSBLOCKSAVG_ROW_LEN,以便来看看ix_sel到底取决于哪个值。

 

1、修改#Blks后的10053

SQL> exec dbms_stats.set_table_stats(ownname => 'IPRA',tabname => 'TB0624',numblks => 538);

 

PL/SQL procedure successfully completed

 

SQL> SELECT NUM_ROWS,BLOCKS,AVG_ROW_LEN FROM USER_TABLES WHERE TABLE_NAME='TB0624';

 

  NUM_ROWS     BLOCKS AVG_ROW_LEN

---------- ---------- -----------

     20010        538          14

 

***************************************

BASE STATISTICAL INFORMATION

***********************

Table Stats::

  Table: TB0624  Alias: TB0624

    #Rows: 20010  #Blks:  538  AvgRowLen:  14.00

Index Stats::

  Index: IDX_TYPE  Col#: 1

    LVLS: 1  #LB: 40  #DK: 3  LB/K: 13.00  DB/K: 267.00  CLUF: 801.00

***************************************

SINGLE TABLE ACCESS PATH

  Column (#1): TYPE(NUMBER)  NO STATISTICS (using defaults)

    AvgLen: 22.00 NDV: 625 Nulls: 0 Density: 0.0015992

  Table: TB0624  Alias: TB0624    

    Card: Original: 20010  Rounded: 200  Computed: 200.10  Non Adjusted: 200.10

  Access Path: TableScan

    Cost:  121.28  Resp: 121.28  Degree: 0

      Cost_io: 119.00  Cost_cpu: 7837335

      Resp_io: 119.00  Resp_cpu: 7837335

  Access Path: index (AllEqGuess)

    Index: IDX_TYPE

    resc_io: 17.00  resc_cpu: 151884

    ix_sel: 0.004  ix_sel_with_filters: 0.004

    Cost: 17.04  Resp: 17.04  Degree: 1

  Best:: AccessPath: IndexRange  Index: IDX_TYPE

         Cost: 17.04  Degree: 1  Resp: 17.04  Card: 200.10  Bytes: 0

可以看到,当我在只改变#Blks的情况下,ix_sel的值未变。

 

2、修改#Rows后的10053

SQL> exec dbms_stats.set_table_stats(ownname => 'IPRA',tabname => 'TB0624',numblks => 438,numrows => 30010);

 

PL/SQL procedure successfully completed

 

SQL> SELECT NUM_ROWS,BLOCKS,AVG_ROW_LEN FROM USER_TABLES WHERE TABLE_NAME='TB0624';

 

  NUM_ROWS     BLOCKS AVG_ROW_LEN

---------- ---------- -----------

     30010        438          14

 

***************************************

BASE STATISTICAL INFORMATION

***********************

Table Stats::

  Table: TB0624  Alias: TB0624

    #Rows: 30010  #Blks:  438  AvgRowLen:  14.00

Index Stats::

  Index: IDX_TYPE  Col#: 1

    LVLS: 1  #LB: 40  #DK: 3  LB/K: 13.00  DB/K: 267.00  CLUF: 801.00

***************************************

SINGLE TABLE ACCESS PATH

  Column (#1): TYPE(NUMBER)  NO STATISTICS (using defaults)

    AvgLen: 22.00 NDV: 938 Nulls: 0 Density: 0.0010663

  Table: TB0624  Alias: TB0624    

    Card: Original: 30010  Rounded: 300  Computed: 300.10  Non Adjusted: 300.10

  Access Path: TableScan

    Cost:  100.66  Resp: 100.66  Degree: 0

      Cost_io: 98.00  Cost_cpu: 9127191

      Resp_io: 98.00  Resp_cpu: 9127191

  Access Path: index (AllEqGuess)

    Index: IDX_TYPE

    resc_io: 18.00  resc_cpu: 173806

    ix_sel: 0.005999  ix_sel_with_filters: 0.005999

    Cost: 18.05  Resp: 18.05  Degree: 1

  Best:: AccessPath: IndexRange  Index: IDX_TYPE

         Cost: 18.05  Degree: 1  Resp: 18.05  Card: 300.10  Bytes: 0

可以看到,当我在只改变#ROWS的情况下,ix_sel的值已经发生了改变。

 

3、修改AvgRowLen后的10053

SQL> exec dbms_stats.set_table_stats(ownname => 'IPRA',tabname => 'TB0624',numblks => 438,numrows => 20010,avgrlen => 24);

 

PL/SQL procedure successfully completed

 

SQL> SELECT NUM_ROWS,BLOCKS,AVG_ROW_LEN FROM USER_TABLES WHERE TABLE_NAME='TB0624';

 

  NUM_ROWS     BLOCKS AVG_ROW_LEN

---------- ---------- -----------

     20010        438          24

 

***************************************

BASE STATISTICAL INFORMATION

***********************

Table Stats::

  Table: TB0624  Alias: TB0624

    #Rows: 20010  #Blks:  438  AvgRowLen:  24.00

Index Stats::

  Index: IDX_TYPE  Col#: 1

    LVLS: 1  #LB: 40  #DK: 3  LB/K: 13.00  DB/K: 267.00  CLUF: 801.00

***************************************

SINGLE TABLE ACCESS PATH

  Column (#1): TYPE(NUMBER)  NO STATISTICS (using defaults)

    AvgLen: 22.00 NDV: 625 Nulls: 0 Density: 0.0015992

  Table: TB0624  Alias: TB0624    

    Card: Original: 20010  Rounded: 200  Computed: 200.10  Non Adjusted: 200.10

  Access Path: TableScan

    Cost:  100.08  Resp: 100.08  Degree: 0

      Cost_io: 98.00  Cost_cpu: 7125191

      Resp_io: 98.00  Resp_cpu: 7125191

  Access Path: index (AllEqGuess)

    Index: IDX_TYPE

    resc_io: 17.00  resc_cpu: 151884

    ix_sel: 0.004  ix_sel_with_filters: 0.004

    Cost: 17.04  Resp: 17.04  Degree: 1

  Best:: AccessPath: IndexRange  Index: IDX_TYPE

         Cost: 17.04  Degree: 1  Resp: 17.04  Card: 200.10  Bytes: 0

可以看到,当我在只改变AvgRowLen的情况下,ix_sel的值未变。

 

从上述测试中我们可以很清晰的得出如下结论:

在无统计信息的情况下,ix_sel的值取决于#Rows,而不是取决于#Blks

No TrackBacks

TrackBack URL: http://dbsnake.com/cgi-bin/mt/mt-tb.cgi/49

1 Comment

ix_sel是指索引的选择性,表示索引字段的值的行数占总行数的比例,所以总行数变了,这个值就会变。而且该索引列的直方图变了,或者查询中的列的值变了,该值也会变。

Leave a comment