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

注意:动态采样在Oracle 11g之前称为 Dynamic Sampling, ORACLE 12c之后改名为Dynamic Statistic.

Oracle11G R2 默认的采样级别:

SQL> show parameter optimizer_dynamic_sampling

NAME                                 TYPE        VALUE

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

optimizer_dynamic_sampling           integer     2

SQL> show parameter Dynamic Statistic

NAME                                 TYPE        VALUE

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

optimizer_dynamic_sampling           integer     2

动态采样的级别有11个级别:请自行查看官方文档

http://docs.oracle.com/cd/E11882_01/server.112/e41573/stats.htm#PFGRF30101

动态采样实验:

1、创建测试表test

SQL> create table test as select * from dba_objects;

Table created.

SQL> select count(1) from test;

COUNT(1)

----------

86259

2、不使用动态采样,查看执行计划

SQL> set autotrace traceonly explain;

SQL> select /*+ dynamic_sampling(test 0) */ * from test;

Execution Plan

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

Plan hash value: 1357081020

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

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |      |   100K|    19M|   336   (1)| 00:00:05 |

|   1 |  TABLE ACCESS FULL| TEST |   100K|    19M|   336   (1)| 00:00:05 |

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

Note

-----

- dynamic sampling used for this statement (level=2)

从上面可以看出,次数优化器估计表test的行数显示为100K,我们再看下面使用动态采样的执行计划,优化器会估算多少行:

3、使用动态采样,查看执行计划(下面是直接查询的,因为在11G 是默认启用动态采样的)

SQL> select * from test;

Execution Plan

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

Plan hash value: 1357081020

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

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |      | 72258 |    14M|   336   (1)| 00:00:05 |

|   1 |  TABLE ACCESS FULL| TEST | 72258 |    14M|   336   (1)| 00:00:05 |

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

Note

-----

- dynamic sampling used for this statement (level=2)

如果启用动态采样(默认情况下,动态采样级别为2),优化器根据动态采样得到一些数据信息猜测、估计表TEST的记录行数为86259,已经接近实际记录行数72258了。比不做动态采样分析要好很多了。

如果我们将动态采样的级别提高为3,如下所示,发现优化器根据动态采样得到的信息比默认(默认情况下,动态采样级别为2)情况获得的信息更准确。优化器估计表TEST的行数为92364,比72258又接近实际情况一步了。

SQL> select /*+ dynamic_sampling(test 3) */ * from test;

Execution Plan

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

Plan hash value: 1357081020

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

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |      | 92364 |    18M|   336   (1)| 00:00:05 |

|   1 |  TABLE ACCESS FULL| TEST | 92364 |    18M|   336   (1)| 00:00:05 |

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

Note

-----

- dynamic sampling used for this statement (level=2)

4、在Tom大师的这篇文章中提到,在没有动态采样的情况下,如果删除了该表数据,CBO优化器估算的结果集和没有删除之前是一样的。

这是因为当一个表的数据被删除后,这个表所分配的extent和block是不会自动回收的(高水位线不变),所以CBO如果没有采样数据块做分析,只是从数据字典中获取extend等信息,就会误认为任然还有那么多数据。下面我们把test表数据清空,看看执行计划如何

SQL> delete from test;

86259 rows deleted.

SQL> commit;

SQL> select /*+ dynamic_sampling(test 0) */ * from test;    ----不使用动态采样

Execution Plan

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

Plan hash value: 1357081020

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

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |      |   100K|    19M|   336   (1)| 00:00:05 |

|   1 |  TABLE ACCESS FULL| TEST |   100K|    19M|   336   (1)| 00:00:05 |

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

SQL> select * from test;                   -----使用动态采样

Execution Plan

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

Plan hash value: 1357081020

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

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |      |     1 |   207 |   335   (0)| 00:00:05 |

|   1 |  TABLE ACCESS FULL| TEST |     1 |   207 |   335   (0)| 00:00:05 |

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

Note

-----

- dynamic sampling used for this statement (level=2)

从上面的查看可以看出,不采用动态采样和采用动态采样的区别;

5、我们对test表收集下统计信息:再次查询,该表的执行计划就会少了:dynamic sampling

SQL> select * from test;

Execution Plan

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

Plan hash value: 1357081020

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

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |      |     1 |   207 |   335   (0)| 00:00:05 |

|   1 |  TABLE ACCESS FULL| TEST |     1 |   207 |   335   (0)| 00:00:05 |

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

SQL>

第二种情况:当表TEST即使被分析过,如果查询脚本里面包含临时表,就会使用动态采样技术。因为临时表是不会被分析,它是没有统计信息的。如下所示:

SQL> drop table test;

SQL> create table test as select * from dba_objects;

SQL> exec dbms_stats.gather_table_stats(ownname =>'SYS',tabname =>'TEST',cascade=>TRUE);

SQL> create global temporary table tmp (object_type varchar2(19));

SQL> insert into tmp select distinct object_type from dba_objects;

44 rows created.

SQL> commit;

然后查看下面查询语句的执行计划:

SQL> select t.owner,l.object_type from test t inner join tmp l on t.object_type=l.object_type;

Execution Plan

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

Plan hash value: 19574435

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

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT   |      |     1 |    26 |   338   (1)| 00:00:05 |

|*  1 |  HASH JOIN         |      |     1 |    26 |   338   (1)| 00:00:05 |

|   2 |   TABLE ACCESS FULL| TMP  |     1 |    11 |     2   (0)| 00:00:01 |

|   3 |   TABLE ACCESS FULL| TEST | 86260 |  1263K|   336   (1)| 00:00:05 |

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

Predicate Information (identified by operation id):

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

1 - access("T"."OBJECT_TYPE"="L"."OBJECT_TYPE")

Note

-----

- dynamic sampling used for this statement (level=2)

SQL>

从上面可以看到 虽然是对tmp表执行的而是全表扫描,但是优化器只是估算了1行数据

6、动态采样还有一个独特能力,可以对不同列之间的相关性做统计。

表统计信息都是相对独立的。当查询涉及列之间的相关性时,统计信息就显得有些不足了,请看Tom大师的例子

6.1、创建一个特殊的表t,然后对字段flag1、flag2创建索引t_idx,然后分析收集统计信息

SQL> 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;

SQL> create index t_idx on t(flag1, flag2);

SQL> begin

dbms_stats.gather_table_stats(user, 'T',

method_opt =>'for all indexed columns size 254');

end;

/

PL/SQL procedure successfully completed.

6.2、查看表的行数:

SQL> select num_rows, num_rows/2, num_rows/2/2 from user_tables  where table_name='T';

NUM_ROWS NUM_ROWS/2 NUM_ROWS/2/2

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

84396      42198        21099

6.3、看看对flag1过滤条件的SQL语句的执行计划:

SQL> select * from t where flag1='N';

Execution Plan

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

Plan hash value: 1601196873

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

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |      | 42937 |  4276K|   342   (1)| 00:00:05 |

|*  1 |  TABLE ACCESS FULL| T    | 42937 |  4276K|   342   (1)| 00:00:05 |

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

Predicate Information (identified by operation id):

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

1 - filter("FLAG1"='N')

从上面的执行计划可以看出:CBO优化器猜测、估计的行数42937, 相当接近42198记录数了

6.4、看看对flag2过滤条件的SQL语句的执行计划:

SQL> select * from t where flag2='N';

Execution Plan

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

Plan hash value: 1601196873

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

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |      | 41459 |  4129K|   342   (1)| 00:00:05 |

|*  1 |  TABLE ACCESS FULL| T    | 41459 |  4129K|   342   (1)| 00:00:05 |

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

Predicate Information (identified by operation id):

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

1 - filter("FLAG2"='N')

从上面的执行计划可以看出:CBO优化器猜测、估计的行数41459, 相当接近42198记录数了

6.5、如果条件flag1 = 'N' and flag2 = 'N',我们根据逻辑推理判断这样的记录肯定是不存在的,这也是苦心构造这个特例的初衷。下面看看CBO优化器怎么探测、预测的

SQL> select * from t where flag1 = 'N' and flag2 = 'N';

Execution Plan

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

Plan hash value: 1601196873

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

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |      | 21093 |  2101K|   342   (1)| 00:00:05 |

|*  1 |  TABLE ACCESS FULL| T    | 21093 |  2101K|   342   (1)| 00:00:05 |

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

Predicate Information (identified by operation id):

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

1 - filter("FLAG2"='N' AND "FLAG1"='N')

从上面看:CBO估计的记录数为12468,和实际情况相差非常远。其实是CBO优化器这样估算来的:

flag1=‘N' 的记录数占总数的1/2

flag2= 'N' 的记录数占总数的1/2

6.6、根据NUM_ROWS/2/2 =12468.这样显然是不合理的。下面我们通过提升动态采样级别,来看看动态采样是否能避免CBO的错误:

SQL> select /*+ dynamic_sampling(t 3) */ * from t where flag1 = 'N' and flag2 = 'N';

Execution Plan

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

Plan hash value: 470836197

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

| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT            |       |     6 |   612 |     2   (0)| 00:00:01 |

|   1 |  TABLE ACCESS BY INDEX ROWID| T     |     6 |   612 |     2   (0)| 00:00:01 |

|*  2 |   INDEX RANGE SCAN          | T_IDX |     6 |       |     1   (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

2 - access("FLAG1"='N' AND "FLAG2"='N')

Note

-----

- dynamic sampling used for this statement (level=2)

注意:

①:采样级别越高,采样的数据块越多,得到的分析数据就越接近于真实,但同时伴随着资源消耗的开销也增加了。这时一个需要权衡考虑的东西。ORACLE 10 g & 11g的默认采样级别都为2,一般使用在会话中使用dynamic_sampling提示来修改动态采样级别。

②:凡事有利必有弊,动态采样也不是神器。它采样的数据块越多,系统开销就越大,这样会增加SQL硬解析的时间,如果是数据库仓库(DW、OLAP)环境,SQL执行时间相当长,硬解析时间只占整个SQL执行时间的一小部分,那么可以适当的提高动态采样级别,这样是有利于优化器获取更加正确的信息。一般设置为3或4比较合适。

③:在并发比较严重的OLTP系统中,每秒中有成千上万的SQL语句执行,它要求SQL语句短小、执行时间短,所以在OLTP系统中应该减低动态采样级别或不用动态采样。

转载于:https://blog.51cto.com/fengfeng688/1920186

Oracle动态采样学习相关推荐

  1. oracle 抽样_深入理解Oracle动态采样

    Oracle 动态采样( Dynamic Sampling , 12c 称为 Dynamic statistics) ,是对统计信息的⼀一个重要补充,当数 据动态变化,⽆无法⽤用典型的统计信息描述时, ...

  2. oracle动态采样超时,解决 ORACLE 11.2 动态采样导致的性能问题

    [赛迪网报道]我们知道动态采样一般在没有统计信息的时候生效,但我们表都有最新的统计信息.为什么会这样呢?BUG 就算是level8的采样,也不过千百个block,肯定不准确,这个问题是发生在 我经过一 ...

  3. Oracle动态采样详解

     动态采样原博客链接:http://czmmiao.iteye.com/blog/1484571 动态采样概述 动态采样(Dynamic Sampling)技术的最初提出是在Oracle 9i R ...

  4. Oracle 分析及动态采样

    之前在说Oracle Optimizer中的CBO时讲到,当表没有做分析的时候,Oracle 会使用动态采样来收集统计信息. 获取准确的段对象(表,表分区,索引等)的分析数据,是CBO存在的基石,CB ...

  5. Oracle优化07-分析及动态采样-动态采样

    思维导图 07系列文章 Oracle优化07-分析及动态采样-直方图 Oracle优化07-分析及动态采样-DBMS_STATS 包 Oracle优化07-分析及动态采样-动态采样 动态采样Dynam ...

  6. Oracle优化07-分析及动态采样-DBMS_STATS 包

    思维导图 07系列文章 Oracle优化07-分析及动态采样-直方图 Oracle优化07-分析及动态采样-DBMS_STATS 包 Oracle优化07-分析及动态采样-动态采样 DBMS_STAT ...

  7. Oracle优化07-分析及动态采样-直方图

    思维导图 07系列文章 Oracle优化07-分析及动态采样-直方图 Oracle优化07-分析及动态采样-DBMS_STATS 包 Oracle优化07-分析及动态采样-动态采样 概述 获取准确的段 ...

  8. Oracle 12c 新特性:SQL Plan Directives与过量的动态采样解析

    在 12c 中,优化器进行了较大的改变,推出了 Adaptive query optimization,从整体上说,Adaptive query optimization 可以看作如下两部分: 一部分 ...

  9. oracle临时表动态采样,带临时表的SQL查询语句的优化方法

    [IT168 原创]故障突发:11号上午,收到系统应用人员的反馈:"销售日报"无法查询出结果,已经等待一个小时,屏幕依然是灰的,而以往该报表2分钟内即可出结果,IT部的同事看一下怎 ...

最新文章

  1. CVPR2020:三维实例分割与目标检测
  2. signature=2ee20a16234208d4dd8bbd7fe87bb472,sstk-20200428
  3. 时间序列:等分布序列(Equidistributed sequence)
  4. jQuery之end()和pushStack()
  5. Android动态权限申请
  6. 数据结构与算法-day3-归并 快速排序
  7. 如何搭建一套完整的深度学习系统?
  8. java登陆挤下去代码_application作用域实现用户登录挤掉之前登录用户代码
  9. android继承图,Android图形系统(三)-View绘制流程
  10. 物体检测object detection object recognition和coco数据集 动手学深度学习v2 pytorch
  11. WPS office 下载
  12. 大厂必背 MySQL优化面试题
  13. mysql数据库学习汇总
  14. Postgis使用工具raster2pgsql批量导入栅格数据(一)
  15. 特征工程与表示学习:人工 vs 自动
  16. 华东师范大学、普陀区科委领导一行莅临和数集团
  17. 向量组是否相关与行列式,方程组,秩的联系。
  18. 仅仅有人物没背景的图片怎么弄_纯干货//只会画人物不会画背景?这3种方法教你快速画背景!...
  19. 华为云CDN如何提高缓存命中率
  20. 一个让围棋软件自动对弈的工具

热门文章

  1. hive replace替换多个_详解Mysql数据库中replace与replace into的用法及区别
  2. window.opener.document.getElementById(“a”)用标准的Jquery 语言怎么写
  3. linux 火狐安装java插件_Linux下Firefox安装配置JDK插件
  4. android edittext html 图片,Android EditText加载HTML内容(内容包含网络图片) -电脑资料...
  5. oracle rac 磁盘重建,Oracle RAC环境下重建ASM磁盘组 Re-create ASM diskgroup with Oracle RAC...
  6. android view爆炸效果,Android 显示view的粒子爆炸/绽放效果
  7. 智能车竞赛线上比赛部分镜头
  8. FootSwitch脚踏开关:三位USB静音脚踏板脚踏开关脚踏键盘鼠标
  9. 逐飞mini车样品说明
  10. 为什么面包板不能够做射频电路实验?