11g Multi-Column Correlation Stats and Dynamic Sampling

Oracle CBO优化模式中列的统计信息是一个十分重要的概念,但在11g之前我们所讨论的都是基于单列的统计信息或直方图,也就是说基于成本的优化器总是假设where子句后的谓词中列与列之间不存在联系。但是有的查询包含一个表的多个列,而每个列又都与不同的选择度。这些列中有的是相关的,但优化器并不知道这些关系。在这种情况下,优化器如果要估计出真实的基数(card),必须要了解增加另一列到某个给定列是否会引起结果集的减少。多列上的相关统计数据能提供比单列统计数据或直方图更好的基数估计。当2个列紧密相关时,增加额外的谓词可以减少结果集。Oracle database 11g中引入了扩展统计(也叫多列统计,multicolumn statistics),可以收集一组列上的统计数据,从而让优化器能准确地计算多个单列谓词的选择性。因为把紧密相关的列作为一个组才能正确地放映其组合选择性,所以把相关列作为一组,在其上(列祖)收集统计数据,这些信息足以让优化器能准确地进行选择性估计,在包含使用相关列的谓词查询中,这是我们实际关心的问题。多列统计的引入意味着,在11g中cbo优化器可以对具有多列复杂谓词判断的SQL语句做出更准确的成本估算,许多原本"误用"全表扫描的查询现在可以使用索引扫描的执行计划,语句将运行地更快速。 我们试看下例:
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

SQL> conn maclean/maclean
Connected.

SQL> drop table YOUYUS;
Table dropped.

/*  建立测试样本表YOUYUS * /

SQL> create table YOUYUS as
  2  select mod(i, 99) t1, mod(i, 99) t2, mod(i, 49) t3, mod(i, 9) t4
  3    from (select rownum i from dual connect by level <= 10001);
Table created.

SQL> exec dbms_stats.gather_table_stats('MACLEAN','YOUYUS',estimate_percent => 100,method_opt => 'FOR ALL COLUMNS SIZE 254');
PL/SQL procedure successfully completed.

SQL>  select count(*) from YOUYUS where t1=1;
  COUNT(*)
----------
       102

SQL> select count(*) from YOUYUS where t2=1;
  COUNT(*)
----------
       102

SQL> alter session set events '10053 trace name context forever,level 1';
Session altered.

SQL> explain plan for
  2  select count(*) from YOUYUS where t1=1 and t2=1;
Explained.

SQL>  alter session set events '10053 trace name context off';
Session altered.

SQL> select count(*) from YOUYUS where t1=1 and t2=1;
  COUNT(*)
----------
       102

SQL> select * from  table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3131921661
----------------------------------------------------------------------------
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |     1 |    12 |     9   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| YOUYUS |     1 |    12 |     9   (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
   1 - filter("T1"=1 AND "T2"=1)
13 rows selected.

/*  cbo优化器预测符合条件的记录为1条,这个数字是通过计算Cardinality基数获得的,下面会讲到 */

/* 11g中无需再使用gettrcname脚本来获取trc文件名了,直接查询v$process视图上的tracefile字段 */

SQL> select tracefile
  2    from v$process
  3   where addr = (select paddr
  4                   from v$session
  5                  where sid = (select distinct sid from v$mystat));
TRACEFILE
--------------------------------------------------------------------------------
/home/maclean/app/maclean/diag/rdbms/sprod/SPROD/trace/SPROD_ora_5662.trc

SQL> host

[maclean@rh2 ~]$ cat /home/maclean/app/maclean/diag/rdbms/sprod/SPROD/trace/SPROD_ora_5662.trc|grep  -A 7  "Cardinality Estimation"
  Single Table Cardinality Estimation for YOUYUS[YOUYUS]
  Column (#1):
    NewDensity:0.005049, OldDensity:0.000050 BktCnt:10001, PopBktCnt:10001, PopValCnt:99, NDV:99
  Column (#2):
    NewDensity:0.005049, OldDensity:0.000050 BktCnt:10001, PopBktCnt:10001, PopValCnt:99, NDV:99
  Table: YOUYUS  Alias: YOUYUS
    Card: Original: 10001.000000  Rounded: 1  Computed: 1.04  Non Adjusted: 1.04

/*   传统的统计信息只有单列的直方图信息,对于多谓词情况下cbo优化器计算Cardinality的公式为
      Cardinality=Original Card * (1/predicate1_NDV) * (1/ predicate2_NDV) = 10001 * (1/99)* (1/99)= 1
      这同实际的结果102条记录符合条件有着巨大差距
*/

/* 如果我们使用11g中的Extend stats 统计信息又会如何呢? * /

  function create_extended_stats(
      ownname    varchar2,
      tabname    varchar2,
      extension  varchar2)
    return varchar2;

-- This function creates a column stats entry in the system for a user specified
-- column group or an expression in a table. Statistics for this extension will
-- be gathered when user or auto statistics gathering job gathers statistics for
-- the table. We call statistics for such an extension, "extended statistics".
-- This function returns the name of this newly created entry for the extension.
-- If the extension already exists then this function  throws an error.

--
--  Parameters:
--      ownname       -- owner name of a table
--      tabname       -- table name
--      extension     -- can be either a column group or an expression. Suppose
--                       the specified table has two column c1, c2. An example
--                       column group can be '(c1, c2)', an example expression
--                       can be '(c1 + c2)'.
--
--  Notes:
--
--      1. An extension cannot contain a virtual column.
--
--      2. You can not create extensions on tables owned by SYS.
--
--      3. You can not create extensions on cluster tables, index organized
--         tables, temporary tables, external tables.
--
--      4. Total number of extensions in a table cannot be greater than
--         maximum of (20, 10 % of number of non-virtual columns in the table).
--
--      5. Number of columns in a column group must be in the range [2, 32].
--
--      6. A column can not appear more than once in a column group.
--
--      7. Column group can not contain expressions.
--
--      8. An expression must contain at least one column.
--
--      9. An expression can not contain subquery.
--
--     10. COMPATIBLE parameter needs to be 11.0.0.0.0 or greater.

/* 通过create_extended_stats可以建立一个列组,extension属性列出作为新列组的相关列 */

SQL> select  dbms_stats.create_extended_stats(ownname => 'MACLEAN',tabname => 'YOUYUS',extension => '(t1,t2)' ) as YOUYUS_EXTEND_STATS from dual;
YOUYUS_EXTEND_STATS
--------------------------------------------------------------------------------
SYS_STUW_4TRBM2QR4LKRT$EY6VJ$E

SQL> set linesize 200;

SQL> select  EXTENSION_NAME,EXTENSION from dba_stat_extensions where table_name='YOUYUS';

EXTENSION_NAME                      EXTENSION
----------------------------------- --------------------------------------------------------------------------------
SYS_STUW_4TRBM2QR4LKRT$EY6VJ$E      ("T1","T2")

SQL> exec dbms_stats.gather_table_stats('MACLEAN','YOUYUS',estimate_percent => 100,method_opt => 'FOR ALL COLUMNS SIZE 254');
PL/SQL procedure successfully completed.

/* 在使用FOL ALL COLUMNS的method_opt时将会收集(t1,t2)扩展列组的直方图等信息 */

SQL> select COLUMN_NAME, NUM_DISTINCT
  2    from dba_tab_col_statistics
  3   where table_name = 'YOUYUS'
  4     and owner = 'MACLEAN'
  5     and column_name like 'SYS%';
COLUMN_NAME                    NUM_DISTINCT
------------------------------ ------------
SYS_STUW_4TRBM2QR4LKRT$EY6VJ$E           99

/* 可以而看到这里多出了Extend Stats(t1,t2)的 统计信息 * /

SQL> alter session set events '10053 trace name context forever,level 1';
Session altered.

SQL> explain plan for
  2  select count(*) from YOUYUS where t1=1 and t2=1;
Explained.

SQL> alter session set events '10053 trace name context off';
Session altered.

SQL> select * from  table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2542806819
-----------------------------------------------------------------------------
| Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |        |     1 |     6 |     9   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |        |     1 |     6 |            |          |
|*  2 |   TABLE ACCESS FULL| YOUYUS |   102 |   612 |     9   (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------
   2 - filter("T1"=1 AND "T2"=1)
14 rows selected.

/* 收集了(t1,t2)相关列的统计信息后,cbo优化器给出了正确的 Cardinality=102*/

SQL> select tracefile
  2    from v$process
  3   where addr = (select paddr
  4                   from v$session
  5                  where sid = (select distinct sid from v$mystat));
TRACEFILE
--------------------------------------------------------------------------------
/home/maclean/app/maclean/diag/rdbms/sprod/SPROD/trace/SPROD_ora_5807.trc

SQL> host
[maclean@rh2 ~]$ cat /home/maclean/app/maclean/diag/rdbms/sprod/SPROD/trace/SPROD_ora_5807.trc|grep -A 11  "Cardinality Estimation"
  Single Table Cardinality Estimation for YOUYUS[YOUYUS]
  Column (#1):
    NewDensity:0.005049, OldDensity:0.000050 BktCnt:10001, PopBktCnt:10001, PopValCnt:99, NDV:99
  Column (#2):
    NewDensity:0.005049, OldDensity:0.000050 BktCnt:10001, PopBktCnt:10001, PopValCnt:99, NDV:99
  Column (#5):
    NewDensity:0.005049, OldDensity:0.000050 BktCnt:10001, PopBktCnt:10001, PopValCnt:99, NDV:99
  ColGroup (#1, VC) SYS_STUW_4TRBM2QR4LKRT$EY6VJ$E
    Col#: 1 2    CorStregth: 99.00
  ColGroup Usage:: PredCnt: 2  Matches Full: #1  Partial:  Sel: 0.0102
  Table: YOUYUS  Alias: YOUYUS
    Card: Original: 10001.000000  Rounded: 102  Computed: 102.00  Non Adjusted: 102.00

/* 10053事件trace表明cbo优化器考虑使用了SYS_STUW_4TRBM2QR4LKRT$EY6VJ$E的Extend stats * /

/* 通过dbms_stats.drop_extended_stats存储过程删除扩展列组 * /

SQL>  exec dbms_stats.drop_extended_stats(ownname => 'MACLEAN',tabname => 'YOUYUS',extension => '(t1,t2)' ) ;
PL/SQL procedure successfully completed.
是不是很cool?有了multicolumn statistics多列统计之后cbo优化器对于多谓词的语句可以做出更准确的成本估算了,但是一张张表去分析哪些列需要建成多列统计的列组不是很麻烦吗?不要紧11g中加强了动态统计信息的收集,它或许可以帮到我们:
SQL> conn sh/sh
Connected.

SQL> show parameter dyna

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_dynamic_sampling           integer     2

/* 11g中默认的optimizer_dynamic_sampling 仍为2,当表上没有统计信息时将会引发动态采样 * /

SQL> select count(*) from customers where cust_city='Greenwich' and cust_credit_limit=5000;
  COUNT(*)
----------
        96

SQL> exec dbms_stats.delete_table_stats(ownname=>'SH',tabname=>'CUSTOMERS');
PL/SQL procedure successfully completed.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2008213504

-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |    47 | 14006 |   405   (1)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| CUSTOMERS |    47 | 14006 |   405   (1)| 00:00:05 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - filter("CUST_CITY"='Greenwich' AND "CUST_CREDIT_LIMIT"=5000)

Note
-----
   - dynamic sampling used for this statement (level=2)
17 rows selected.

/* 2级动态采样将分析63个数据块,可以看到收集的信息还不足以让cbo做出近似基数计算 */

/* 下为2级采样期间的10053 trace * /

  Single Table Cardinality Estimation for CUSTOMERS[CUSTOMERS]

*** 2010-09-03 23:18:55.588
** Performing dynamic sampling initial checks. **
** Dynamic sampling initial checks returning TRUE (level = 2).
** Dynamic sampling updated table stats.: blocks=1486

*** 2010-09-03 23:18:55.589
** Generated dynamic sampling query:
    query text :
SELECT /* OPT_DYN_SAMP */ /*+ ALL_ROWS IGNORE_WHERE_CLAUSE NO_PARALLEL(SAMPLESUB) opt_param('parallel_execution_enabled', 'false') NO_PARALLEL_INDEX(SAMPLESUB) NO_SQL_TUNE */ NVL(SUM(C1),0), NVL(SU
M(C2),0) FROM (SELECT /*+ IGNORE_WHERE_CLAUSE NO_PARALLEL("CUSTOMERS") FULL("CUSTOMERS") NO_PARALLEL_INDEX("CUSTOMERS") */ 1 AS C1, CASE WHEN "CUSTOMERS"."CUST_CITY"='Greenwich' AND "CUSTOMERS"."CU
ST_CREDIT_LIMIT"=5000 THEN 1 ELSE 0 END AS C2 FROM "CUSTOMERS" SAMPLE BLOCK (4.239569 , 1) SEED (1) "CUSTOMERS") SAMPLESUB

*** 2010-09-03 23:18:55.592
** Executed dynamic sampling query:
    level : 2
    sample pct. : 4.239569
    actual sample size : 2025
    filtered sample card. : 2
    orig. card. : 121377
    block cnt. table stat. : 1486
    block cnt. for sampling: 1486
    max. sample block cnt. : 64
    sample block cnt. : 63
    min. sel. est. : 0.00010000
** Using dynamic sampling card. : 47764
** Dynamic sampling updated table card.
** Using single table dynamic sel. est. : 0.00098765
  Table: CUSTOMERS  Alias: CUSTOMERS
    Card: Original: 47764.285714  Rounded: 47  Computed: 47.17  Non Adjusted: 47.17

/* 可以看到level : 2时sample block cnt为63 * /

SQL> exec dbms_stats.gather_table_stats(ownname=>'SH',tabname=>'CUSTOMERS',estimate_percent => 100,method_opt => 'FOR ALL COLUMNS SIZE 254');
PL/SQL procedure successfully completed.

/* 我们对CUSTOMERS表及表上各列做了详细分析;在表上有统计信息的情况下,2级动态采样将"不作为"  */

SQL> explain plan for
  2  select * from customers where cust_city='Greenwich' and cust_credit_limit=5000;

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2008213504

-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |    12 |  2316 |   405   (1)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| CUSTOMERS |    12 |  2316 |   405   (1)| 00:00:05 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - filter("CUST_CITY"='Greenwich' AND "CUST_CREDIT_LIMIT"=5000)

13 rows selected.

/*
     因为没有为cust_city和CUST_CREDIT_LIMIT 2列组成的列组做动态分析,也没有相关列祖的正式统计信息;
     cbo使用传统单列统计信息做出了比动态统计情况下更糟糕的基数预计
*/

/*
     当使用4级动态采样时,即便表上有正式的统计信息,只要where子句后包含有多个以and或or连接的复杂的谓词判断,
     Oracle仍会针对谓词判断对应的多列做样本为31个数据块的分析
*/

SQL> alter session set optimizer_dynamic_sampling=4;
Session altered.

QL>  alter session set events '10053 trace name context forever,level 1';

Session altered.

SQL>
SQL> explain plan for
  2  select * from customers where cust_city='Greenwich' and cust_credit_limit=5000;

Explained.

SQL> alter session set events '10053 trace name context off';

Session altered.

SQL>  select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2008213504

-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |    69 | 13317 |   405   (1)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| CUSTOMERS |    69 | 13317 |   405   (1)| 00:00:05 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - filter("CUST_CITY"='Greenwich' AND "CUST_CREDIT_LIMIT"=5000)

Note
-----
   - dynamic sampling used for this statement (level=4)

17 rows selected.

/* 下为4级采样期间的10053 trace * /

  Single Table Cardinality Estimation for CUSTOMERS[CUSTOMERS]

*** 2010-09-03 23:14:01.023
** Performing dynamic sampling initial checks. **
  Column (#16):
    NewDensity:0.016847, OldDensity:0.000009 BktCnt:55500, PopBktCnt:55500, PopValCnt:8, NDV:8
  Column (#9):
    NewDensity:0.001189, OldDensity:0.002179 BktCnt:254, PopBktCnt:77, PopValCnt:34, NDV:620
** Dynamic sampling initial checks returning TRUE (level = 4).

*** 2010-09-03 23:14:01.023
** Generated dynamic sampling query:
    query text :
SELECT /* OPT_DYN_SAMP */ /*+ ALL_ROWS IGNORE_WHERE_CLAUSE NO_PARALLEL(SAMPLESUB) opt_param('parallel_execution_enabled', 'false') NO_PARALLEL_INDEX(SAMPLESUB) NO_SQL_TUNE */ NVL(SUM(C1),0), NVL(SU
M(C2),0) FROM (SELECT /*+ IGNORE_WHERE_CLAUSE NO_PARALLEL("CUSTOMERS") FULL("CUSTOMERS") NO_PARALLEL_INDEX("CUSTOMERS") */ 1 AS C1, CASE WHEN "CUSTOMERS"."CUST_CITY"='Greenwich' AND "CUSTOMERS"."CU
ST_CREDIT_LIMIT"=5000 THEN 1 ELSE 0 END AS C2 FROM "CUSTOMERS" SAMPLE BLOCK (2.086137 , 1) SEED (1) "CUSTOMERS") SAMPLESUB

*** 2010-09-03 23:14:01.025
** Executed dynamic sampling query:
    level : 4
    sample pct. : 2.086137
    actual sample size : 804
    filtered sample card. : 1
    orig. card. : 55500
    block cnt. table stat. : 1486
    block cnt. for sampling: 1486
    max. sample block cnt. : 32
    sample block cnt. : 31
    min. sel. est. : 0.00164375
** Using single table dynamic sel. est. : 0.00124378
  Table: CUSTOMERS  Alias: CUSTOMERS
    Card: Original: 55500.000000  Rounded: 69  Computed: 69.03  Non Adjusted: 69.03

/* 可以看到当sample level : 4时的sample block cnt为31,要少于2级采样触发的时候 */

SQL> alter session set optimizer_dynamic_sampling=10;

Session altered.

SQL> alter session set events '10053 trace name context forever,level 1';

Session altered.

SQL>  explain plan for
  2  select * from customers where cust_city='Greenwich' and cust_credit_limit=5000;

Explained.

SQL>  alter session set events '10053 trace name context off';

Session altered.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2008213504

-------------------------------------------------------------------------------
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |           |    96 | 28608 |   405   (1)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| CUSTOMERS |    96 | 28608 |   405   (1)| 00:00:05 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

   1 - filter("CUST_CITY"='Greenwich' AND "CUST_CREDIT_LIMIT"=5000)

Note
-----
   - dynamic sampling used for this statement (level=10)

17 rows selected.

/* 当10级采样时,cbo给出了完全正确的Cardinality基数 */
/* 让我们看看动态采样是如何做到的 * /

SINGLE TABLE ACCESS PATH
  Single Table Cardinality Estimation for CUSTOMERS[CUSTOMERS]

*** 2010-09-03 22:42:41.661
** Performing dynamic sampling initial checks. **
** Dynamic sampling initial checks returning TRUE (level = 10).
** Dynamic sampling updated table stats.: blocks=1486

*** 2010-09-03 22:42:41.661
** Generated dynamic sampling query:
    query text :
SELECT /* OPT_DYN_SAMP */ /*+ ALL_ROWS IGNORE_WHERE_CLAUSE NO_PARALLEL(SAMPLESUB) opt_param('parallel_execution_enabled', 'false') NO_PARALLEL_INDEX(SAMPLESUB) NO_SQL_TUNE */ NVL(SUM(C1),0), NVL(SU
M(C2),0) FROM (SELECT /*+ IGNORE_WHERE_CLAUSE NO_PARALLEL("CUSTOMERS") FULL("CUSTOMERS") NO_PARALLEL_INDEX("CUSTOMERS") */ 1 AS C1, CASE WHEN "CUSTOMERS"."CUST_CITY"='Greenwich' AND "CUSTOMERS"."CU
ST_CREDIT_LIMIT"=5000 THEN 1 ELSE 0 END AS C2 FROM "CUSTOMERS" "CUSTOMERS") SAMPLESUB

*** 2010-09-03 22:42:41.676
** Executed dynamic sampling query:
    level : 10
    sample pct. : 100.000000
    actual sample size : 55500
    filtered sample card. : 96
    orig. card. : 121377
    block cnt. table stat. : 1486
    block cnt. for sampling: 1486
    max. sample block cnt. : 4294967295
    sample block cnt. : 1486
    min. sel. est. : 0.00010000
** Using dynamic sampling card. : 55500
** Dynamic sampling updated table card.
** Using single table dynamic sel. est. : 0.00172973
  Table: CUSTOMERS  Alias: CUSTOMERS
    Card: Original: 55500.000000  Rounded: 96  Computed: 96.00  Non Adjusted: 96.00

/* 10级动态采用将会分析所有块,其代价过高了  * /
通过以上测试我们可以发现,当默认情况下的单列信息统计无法让cbo做出正确判断时,我们可以采用4级的动态采样来一定程度上满足需求;当然4级的动态采样受限于其样本数量,其所提供的统计信息也并不能让优化器做出十分精确的成本估算。 Oracle optimizer Team最近在其博客中列出了11g中各级别optimizer_dynamic_sampling的具体表现,但我们通过以上测试可以知道这里罗列的各级别的Sample size(blocks)并不准确。
Level When Dynamic Sampling will be used Sample size (blocks)
0 Switches off dynamic sampling N/A
1 At least one non-partitioned table in the statement has no statistics 32
2 (default) One or more tables in the statement have no statistics 64
3 Any statement that meets level 2 criteria and any statement that has one or more expressions used in the where clause predicates e.g. Where substr(CUSTLASTNAME,1,3) or Where a + b =5 64
4 Any statement that meets level 3 criteria and any statement that has complex predicates. An OR or AND operator between multiple predicates on the same table 64
5 Any statement that meets level 4 criteria 128
6 Any statement that meets level 4 criteria 256
7 Any statement that meets level 4 criteria 512
8 Any statement that meets level 4 criteria 1024
9 Any statement that meets level 4 criteria 4086
10 All statements All Blocks
就目前来看扩展统计数据(extended statistics)特性和对动态采样的加强比较适合于复杂的OLTP环境,并且适宜于那些不会反复多次运行的SQL语句。

你可能感兴趣的:(column,dynamic,Predicate,CBO,Cardinality,complicate)