ORACLE动态采样

原文地址:http://www.oracle.com/technetwork/issue-archive/2009/09-jan/o19asktom-086775.html

动态采样是为了解决当硬解析时对没有统计信息的表抽样收集统计信息,让优化器走出合适的执行计划。

从oracle9.2开始,动态采样共有11个级别(从0到10),oracle9.2的默认采样级别为1,oracle10.1及以上版本默认为2.

1.启用动态采样的方法:

  1.1 设置参数OPTIMIZER_DYNAMIC_SAMPLING

  1.2 会用hint  DYNAMIC_SAMPLING

2.当优化器遇到没有统计信息的表时,会尝试动态的收集优化器需要的统计信息。但是对于remote tables和external tables,

无法对其进行动态采样,只能使用默认值,虽然默认值通常和实际的差别比较大:

http://docs.oracle.com/cd/B28359_01/server.111/b28274/stats.htm#i41866

3. 动态采样测试

create table t
    as
   select owner, object_type
      from all_objects

  3.1通过hint禁用动态采样,采样级别设置为0即禁用动态采样

select /*+ dynamic_sampling(t 0) */* from t;

执行计划如下所示:

    --------------------------------------------------------------------------
    | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |      |       |       |    63 (100)|          |
    |   1 |  TABLE ACCESS FULL| T    | 18378 |   502K|    63   (0)| 00:00:01 |
    --------------------------------------------------------------------------

优化器认为只会返回18378,实际t表中有80761条数据,和实际值的差别还是很大的。(不知道为什么如果建表语句为create table t as select *  from all_objects的话,Rows的值会很接近实际值)

  3.2 假设我们不通过hint禁用动态采样,oracle10.1以上版本默认采样级别为2的动态采样

select * from t;

执行计划如下:

7    --------------------------------------------------------------------------
8    | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
9    --------------------------------------------------------------------------
10    |   0 | SELECT STATEMENT  |      |       |       |    64 (100)|          |
11    |   1 |  TABLE ACCESS FULL| T    | 81761 |  2235K|    64   (2)| 00:00:01 |
12    --------------------------------------------------------------------------

38    Note
39    -----
40       - dynamic sampling used for this statement (level=2)

此时优化器的预估返回值81761和80761基本一致,3.1中的示例是优化器对cardinality的估值偏小,

同样存在因为缺乏统计信息导致优化器对cardinality估值偏大的情况

  3.3 对cardinality 估值偏大

我们对删除表t中的数据,然后再次执行3.1中的sql

delete from t;
commit;
select /*+ dynamic_sampling(t 0) */* from t;

得到的执行计划如下所示:

    --------------------------------------------------------------------------
    | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |      |       |       |    63 (100)|          |
    |   1 |  TABLE ACCESS FULL| T    | 18378 |   502K|    63   (0)| 00:00:01 |
    --------------------------------------------------------------------------

和3.1基本没有变化,优化器错误的评估了cardinality。

4. 动态采样的使用情况

  4.1 访问一个刚被创建并导入大量数据且没有收集统计信息的表,比如系统期初上线通常会导入大批量数据,

如果没有来得及对表收集统计信息的话,动态采样就可以发挥作用帮助优化器走出相对合理的执行计划。

  4.2 临时表。临时表通常是没有统计信息的,动态采样可以帮助优化器确定临时表的信息。

5. 对关联列的动态采样

  抛开多列统计信息不谈,动态采样可以动态的收集表中列与列之间的关联关系,如果单纯用dbms_stats对表收集统计信息的话,

是不会知道表中列与列之间的关联关系的。

假设我们有员工信息表,表中有字段员工出生月份BIRTH_MONTH(如5月),星座CONS(如金牛座),一年有12月份,12个星座,

当我们想查询5月出生且星座为金牛座的员工时,可选择率似乎应该是1/12 * 1/12,但是通常情况5月出生的人一大部分都是金牛座。

当应用动态采样的时候,可以近似评估出正常的cardinality。

  5.1 动态采样对关联列评估出来的cardinality测试

drop table t;
create table t
   as select decode( mod(rownum,2), 0, ‘N‘, ‘Y‘ ) flag1,
                 decode( mod(rownum,2), 0, ‘Y‘, ‘N‘ ) flag2, a.*
      from all_objects a
create index t_idx on t(flag1,flag2);
--对表T收集统计信息
BEGIN
  dbms_stats.gather_table_stats(USER,
                                 ‘T‘,
                                 method_opt => ‘for all indexed columns size 254‘);
END;

此时表t中满足条件flag1=‘N‘的数据为39016条,满足flag2=‘N‘的数据也是39016,但是满足条件同时满足flag1=‘N‘和flag2=‘N‘的数据为0条

select * from t where flag1 = ‘N‘ and flag2 = ‘N‘;

执行计划如下所示:

    --------------------------------------------------------------------------
    | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |      |       |       |   325 (100)|          |
    |*  1 |  TABLE ACCESS FULL| T    | 19496 |  1941K|   325   (1)| 00:00:04 |
    --------------------------------------------------------------------------

优化器错误的评估cardinality为19496,和实际值0差别巨大。

通过动态采样可以近似得到实际值:

SELECT /*+ dynamic_sampling(t 3) */
 *
  FROM t
 WHERE flag1 = ‘N‘
       AND flag2 = ‘N‘;

执行计划如下所示:

8    -------------------------------------------------------------------------------------
9    | Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
10    -------------------------------------------------------------------------------------
11    |   0 | SELECT STATEMENT            |       |       |       |     2 (100)|          |
12    |   1 |  TABLE ACCESS BY INDEX ROWID| T     |     6 |   612 |     2   (0)| 00:00:01 |
13    |*  2 |   INDEX RANGE SCAN          | T_IDX |     6 |       |     1   (0)| 00:00:01 |
14    -------------------------------------------------------------------------------------

54    Note
55    -----
56       - dynamic sampling used for this statement (level=2)
57     

评估出来的cardinality仅为6,和实际值0非常接近。(不知道为什么level=2,不应该是3吗?)

6.动态采样的采样级别

http://docs.oracle.com/cd/B19306_01/server.102/b14211/stats.htm#i43032

7.什么时候使用动态采样

  7.1 对OLAP或者数据仓库来说,SQL的执行时间远大于解析时间,建议将采样级别设置3或者4

  7.2 对OLTP系统来说,SQL的解析时间通常大于执行时间,会有很多执行时间很短的SQL,不建议修改默认的采样级别

  

时间: 2024-12-25 17:45:11

ORACLE动态采样的相关文章

Oracle动态采样学习

动态采样(Dynamic Sampling)是在ORACLE 9i Release 2中开始引入的一个技术,引入它的目的是为了应对数据库对象没有分析(统计信息缺失)的情况下,优化器生成更好的执行计划.简单的说,在数据库段(表.索引.分区)对象没有分析的情况下,为了使CBO优化器得到足够多的信息以保证优化器做出正确执行计划而发明的一种技术.它会分析一定数量段对象上的数据块获取CBO需要的统计信息.动态采样技术仅仅是统计信息的一种补充,它不能完全替代统计信息分析. 注意:动态采样在Oracle 11

ORACLE动态采样分析

td {border:solid #9ec9ec; border-width:0px 1px 1px 0px; padding:4px 0px;} table {border:1px solid #9ec9ec; width:100%;border-width:1px 0px 0px 1px;text-align:center;font-size:12px} 动态采样概念 动态采样(Dynamic Sampling)是在ORACLE 9i Release 2中开始引入的一个技术,引入它的目的是为

执行计划基础 动态采样

1. 统计信息默认情况下是每天晚上10点半后收集,如果新建对象还没来得级收集统计信息,就采用动态采样的方式. 2. 具体在set autotrace 跟踪的执行计划中,可以看到类似:- dynamic sampling used for this statement (level=2) 3. 除非你用类似/*+dynamic_sampling(t 0) */的HINT关闭这个动态采样. 4. 在收集过统计信息后,Oracle就不会采用动态采样. 注:建索引过程中,默认会收集索引相关的统计信息.

动态采样---DYNAMIC_SAMPLING 基于tom文章的翻译

我们的技术人员动态地采样,考虑使用情况,并设置水平. 我的问题与动态抽样有关. 它真正做什么,什么时候考虑使用它,以及可以设置的所有不同级别的含义是什么? 动态采样首先在Oracle9 i数据库版本2中可用.基于成本的优化器(CBO)可以在硬解析过程中对查询引用的表进行采样,以确定未分析段的更好的默认统计信息,并验证其"猜测".此抽样仅在硬解析时才会进行,并用于动态生成优化器使用的更好的统计信息,因此名称为动态抽样. 优化器使用各种输入来制定计划. 它使用表上定义的任何和所有约束; 系

Oracle 动态SQL语句

Oracle 动态SQL语句 (2012-06-18 16:36:12) 转载▼ 标签: oracle it   EXECUTE IMMEDIATE代替了以前Oracle8i中DBMS_SQLpackage包. 它解析并马上执行动态的SQL语句或非运行时创建的PL/SQL块.动态创建和执行SQL语句性能超前,EXECUTEIMMEDIATE的目标在于减小企业费用并获得较高的性能,较之以前它相当容易编码.尽管DBMS_SQL仍然可用,但是推荐使用EXECUTEIMMEDIATE,因为它获的收益在包

oracle动态注册参数local_listener

local_listener参数有两种书写格式,提供了不同的功能. 监听文件上,1521和1526端口上都有动态监听端口. [[email protected] admin]$ cat listener.ora LISTENER= (DESCRIPTION= (ADDRESS_LIST= (ADDRESS=(PROTOCOL=tcp)(HOST=dbsv)(PORT=1521)) (ADDRESS=(PROTOCOL=ipc)(KEY=extproc)))) SID_LIST_LISTENER=

Oracle 动态建立分区表

由于数据太多为了加快检索 将一个表建为分区表 在数据插入是动态添加临时表 as -- Local variables here fq_dm varchar(30); p_count number; -- p_fadm number; p_sql varchar(100); begin -- Test statements here --查询zkz的所有分区 -- SELECT partition_name FROM useR_TAB_PARTITIONS WHERE TABLE_NAME='zh

oracle动态注册和静态注册监听器

oracle动态注册和静态注册的区别:动态监听不需要在listener.ora文件中记录关于数据的任何信息,只需要将监听器的配置信息写入到该文件.例如: LISTENER = (DESCRIPTION_LIST =   (DESCRIPTION =    (ADDRESS=(PROTOCOL = IPC) (KEY=EXTPRO1))    (ADDRESS=(PROTOCOL = TCP)(HOST = 192.168.2.29)(PORT = 1521))    ) ) 客户端的tnsnam

Oracle动态性能表-V$SESSION_WAIT,V$SESSION_EVENT

(1)-V$SESSION_WAIT 这是一个寻找性能瓶颈的关键视图.它提供了任何情况下session在数据库中当前正在等待什么(如果session当前什么也没在做,则显示它最后的等待事件).当系统存在性能问题时,本视图可以做为一个起点指明探寻问题的方向. V$SESSION_WAIT中,每一个连接到实例的session都对应一条记录. V$SESSION_WAIT中的常用列 l         SID: session标识 l         EVENT: session当前等待的事件,或者最