Oracle统计信息(三)—— 动态采样(动态统计信息)与 多列统计信息

一、 动态采样 Dynamic Sampling

1. 引入原因

oracle默认认为where条件中出现的各列彼此是没有关联的,以此估算出的基数值可能不准,导致选错执行计划。

例如学生表有10000行,要查询9月出生并且是处女座的人数,如果当作这两个条件没有关联,默认的概率计算方法是(1/12) * (1/12) = 1/144,预估的返回值约为69。但是显然这两个条件是有关联的,9月出生的人大多都是处女座,实际返回行数应该远大于69,而错误的基数预估,就可能导致选错执行计划。

为了较准确地估算where条件中出现有关联关系的列时所有条件组合的选择率,进而得到较准确的基数值,9i R2版本引入了动态采样技术。另外动态采样可以在一定程度上解决因没有统计信息而导致CBO选错执行计划的问题。

12c开始,该特性改名叫做 动态统计信息(Dynamic statistics)

 

2. 动态采样原理

不同的应用、规则千差万别,oracle如何能判断各列间的关系,较准确地得出基数值?

其实,oracle在生成执行计划前,采样选取了表中部分数据块,对采样的数据块实际执行了一次目标sql,这样就能得到这部分数据块的实际返回结果,而它又能通过数据字典查到表中总数据块数,根据这个比例放大实际执行结果,这个结果就可以作为目标sql较准确的基数值。

因此,只要目标表数据分布相对均匀,oracle就能做到无论各列间有什么关系,都能较准确地估算基数值。

注意,动态采样仅适合单表或多表关联的第一个驱动表的select,update,delete语句。如果对多表使用动态采样,oracle无法判断采样哪些数据块更有代表性,可能导致判断错上加错。

 

3. 启用方法

启用方法有两种:

  • 设置参数 optimizer_dynamic_sampling 的值>=1,10gR2以上版本默认值为2,即默认是开启的。
  • 使用动态采样hint:dynamic_sampling(t,level),这里的level对应上面的参数值。
select /*+ dynamic_sampling(t,2) */ * from t where n1=3 and n2=2 and c1='a'

optimizer_dynamic_sampling 参数值含义如下(以下参考自12.1文档):

其中默认采样数据块数由_optimizer_dyn_smp_blks隐含参数控制,默认为32。

Level 含义 默认采样数据块数 (Blocks)

0

不启用

n/a

1

对没有统计信息且满足以下条件的表启用

  • 语句中至少有一个非分区表没有统计信息

  • 该表无索引

  • 该表数据块数必须大于默认采样块数(即32)

32

2

默认值,对没有统计信息的表启用动态采样

64

3

满足以下任意条件时启用:

  • 语句中至少有一个表没有统计信息

  • where语句中使用了一个或多个表达式条件,例如 WHERE SUBSTR(CUSTLASTNAME,1,3)

64

4

满足以下任意条件时启用:

  • 语句中至少有一个表没有统计信息

  • where语句中使用了一个或多个表达式条件,例如 WHERE SUBSTR(CUSTLASTNAME,1,3)

  • 单表查询,且查询条件中出现了至少两列

64

5

The criteria are identical to level 4, but the database uses a different sample size.

128

6

The criteria are identical to level 4, but the database uses a different sample size.

256

7

The criteria are identical to level 4, but the database uses a different sample size.

512

8

The criteria are identical to level 4, but the database uses a different sample size.

1024

9

The criteria are identical to level 4, but the database uses a different sample size.

4086

10

The criteria are identical to level 4, but the database uses a different sample size.

All blocks

11

12c新增等级,在优化器认为oracle需要动态采样数据时自动收集

Automatically determined

 

二、 多列统计信息 MultiColumn Statistics

1. 简介

实际上处理where条件中出现有关联关系的列时不止一种解决方案,11g开始,oracle引入了多列统计信息,也称为组合列统计信息 Column Group Statistics。

11g开始,可以人为指定存在关系的一组列为目标表上的一个组合列,然后使用dbms_stats包对这个组合列收集统计信息,收集到的就是所谓多列统计信息。收集完成后,CBO自然也就知道了组合列的数据分布情况。

 

2. 使用案例

创建cust_state_province和country_id列的Column Group

DECLARE
  cg_name varchar2(30);
BEGIN
  cg_name := dbms_stats.create_extended_stats(null,'customers','(cust_state_province,country_id)');
END;
/

查看column group name

select sys.dbms_stats.show_extended_stats_name('sh','customers','(cust_state_province,country_id)') col_group_name from dual;

COL_GROUP_NAME
--------------------------------------------------------------------------------
SYS_STU#S#WF25Z#QAHIHE#MOFFMM_

通过sys.col$基表可以看到,组合列其实就是在该表中多加了一列,列名为column group name,类似oracle的函数索引。可以从dba_stat_extentions视图中查询目标表所有组合列信息。

--查询多列统计信息
Select extension_name, extension from user_stat_extensions where table_name='CUSTOMERS';

EXTENSION_NAME                EXTENSION
------------------------------ ----------------------------------------
SYS_STU#S#WF25Z#QAHIHE#MOFFMM_   ("CUST_STATE_PROVINCE","COUNTRY_ID")

--查看distinct数和柱状图使用情况
select e.extension col_group, t.num_distinct, t.histogram
  from user_stat_extensions e, user_tab_col_statistics t
 where e.extension_name = t.column_name
   and e.table_name = t.table_name
   and t.table_name = 'CUSTOMERS';

COL_GROUP                              NUM_DISTINCT  HISTOGRAM
---------------------------------------- ------------ ---------------
("CUST_STATE_PROVINCE","COUNTRY_ID")           145  FREQUENCY

收集多列统计信息

--收集已存在的列组统计信息
EXEC DBMS_STATS.GATHER_TABLE_STATS('SH','CUSTOMERS',METHOD_OPT =>'FOR ALL COLUMNS SIZE AUTO');

--收集新指定的列组统计信息
EXEC DBMS_STATS.GATHER_TABLE_STATS('SH','CUSTOMERS',METHOD_OPT =>'FOR ALL COLUMNS SIZE SKEWONLY FOR COLUMNS (CUST_STATE_PROVINCE,COUNTRY_ID) SIZE SKEWONLY');

删除Column Group

exec dbms_stats.drop_extended_stats('sh','customers','(cust_state_province,country_id)');

 

参考

https://docs.oracle.com/database/121/TGSQL/tgsql_astat.htm#TGSQL453

https://docs.oracle.com/database/121/REFRN/GUID-43655FC3-3C32-486B-8B11-8C20C152618D.htm#REFRN10140

http://blog.itpub.net/27126919/viewspace-1655727/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章