size auto与histogram的关系

| No Comments

今天在研究histogram的时候,很偶然的观察到一个skew列,当我指定size auto并收集统计信息后产生的histogram不对。

 

由此引入了一个问题:

"当一个表的某一列的值的分布是skew的时候,这时候如果调用DBMS_STATS.GATHER_TABLE_STATS,并且指定size auto,那么上述skew的列是否一定会产生histogram?"

 

答案是----不一定

skew的列指定size auto并采集统计信息的时候,如果col_usage$里没有skew列的使用信息,那么oracle就不会对上述skew列产生histogram

 

对上述问题,557594.1里有很详细的解释。

我这里转一下557594.1里的测试结果,很能说明问题:

 

SQL> conn dras/acca@armsdev;

Connected to Oracle9i Enterprise Edition Release 9.2.0.6.0

Connected as dras

 

SQL> create table jk_demo (mycol number);

 

Table created

 

SQL> begin

  2  -- create a lot of -1's records

  3  for i in 1..100000 loop

  4  insert into jk_demo values (-1);

  5  end loop;

  6  -- not many 0's

  7  for i in 1..1000 loop

  8  insert into jk_demo values (0);

  9  end loop;

 10  --- not many 7's

 11  for i in 1..100 loop

 12  insert into jk_demo values (7);

 13  end loop;

 14  commit;

 15  end;

 16  /

 

PL/SQL procedure successfully completed

 

SQL> create index jkdemoidx on jk_demo (mycol);

 

Index created

 

SQL> BEGIN

  2  DBMS_STATS.GATHER_TABLE_STATS(OWNNAME =>'DRAS'

  3  ,TABNAME =>'JK_DEMO'

  4  ,METHOD_OPT =>'FOR ALL INDEXED COLUMNS SIZE AUTO'

  5  ,CASCADE =>TRUE);

  6  END;

  7  /

 

PL/SQL procedure successfully completed

 

SQL> select lpad(TABLE_NAME,10), lpad(COLUMN_NAME, 5),

  2  endpoint_number, endpoint_value

  3  from user_histograms

  4  where table_name = 'JK_DEMO';

 

LPAD(TABLE_NAME,10)  LPAD(COLUMN_NAME,5) ENDPOINT_NUMBER ENDPOINT_VALUE

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

   JK_DEMO           MYCOL                             0             -1

   JK_DEMO           MYCOL                             1              7

我们从结果里可以看到这时候对于表JK_DEMOskewmycol,实际上是没有正确的histogram信息的。

 

因为这时候col_usage$里没有列mycol的使用信息

SQL> select object_id from dba_objects where object_name='JK_DEMO';

 

 OBJECT_ID

----------

     57519

 

SQL> select * from sys.col_usage$ where obj#=57519;

 

      OBJ#    INTCOL# EQUALITY_PREDS EQUIJOIN_PREDS NONEQUIJOIN_PREDS RANGE_PREDS LIKE_PREDS NULL_PREDS TIMESTAMP

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

 

 

现在我们来让col_usage$里产生列mycol的使用信息:

SQL> select count(*) from jk_demo where mycol = 1;

 

  COUNT(*)

----------

         0

 

SQL> select * from sys.col_usage$ where obj#=57519;

 

      OBJ#    INTCOL# EQUALITY_PREDS EQUIJOIN_PREDS NONEQUIJOIN_PREDS RANGE_PREDS LIKE_PREDS NULL_PREDS TIMESTAMP

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

 

 

SQL> BEGIN

  2  DBMS_STATS.GATHER_TABLE_STATS(OWNNAME =>'DRAS'

  3  ,TABNAME =>'JK_DEMO'

  4  ,METHOD_OPT =>'FOR ALL INDEXED COLUMNS SIZE AUTO'

  5  ,CASCADE =>TRUE);

  6  END;

  7  /

 

PL/SQL procedure successfully completed

 

SQL> select lpad(TABLE_NAME,10), lpad(COLUMN_NAME, 5),

  2  endpoint_number, endpoint_value

  3  from user_histograms

  4  where table_name = 'JK_DEMO';

 

LPAD(TABLE_NAME,10)  LPAD(COLUMN_NAME,5) ENDPOINT_NUMBER ENDPOINT_VALUE

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

   JK_DEMO           MYCOL                        100000             -1

   JK_DEMO           MYCOL                        101000              0

   JK_DEMO           MYCOL                        101100              7

 

SQL> select * from sys.col_usage$ where obj#=57519;

 

      OBJ#    INTCOL# EQUALITY_PREDS EQUIJOIN_PREDS NONEQUIJOIN_PREDS RANGE_PREDS LIKE_PREDS NULL_PREDS TIMESTAMP

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

     57519          1              1              0                 0           0          0          0 2009-9-4 17

 

我们从结果里可以看到,当我们在sql里用到了列mycol且再次以auto size方式收集统计信息后,不仅col_usage$里有了列mycol的使用信息,而且oracle这里也正确的产生了skewmycolhistogram信息

Leave a comment