详解oracle数据库动态采样(附模拟实验)
概述
假设生产环境中Oracle数据库是每天晚上 10 点收集统计信息,当我们早上 9 点新建了一张表,Oracle 该如何知道这个表的记录大小然后去选择收集统计信息呢?这里就涉及到oracle的动态采样概念了。
动态采样
动态采样(Dynamic Sampling)是在ORACLE 9i Release 2中开始引入的一个技术,引入它的目的是为了应对数据库对象没有分析(统计信息缺失)的情况下,优化器生成更好的执行计划。简单的说,在数据库段(表、索引、分区)对象没有分析的情况下,为了使CBO优化器得到足够多的信息以保证优化器做出正确执行计划而发明的一种技术。它会分析一定数量段对象上的数据块获取CBO需要的统计信息。动态采样技术仅仅是统计信息的一种补充,它不能完全替代统计信息分析。
动态采样增加了那些丢失的或者不足的优化器统计信息。使用动态采样可以让优化器更好的选择谓词。动态采样能够补充类似表中block个数,相关的索引block个数,表的集势(ronded个数),相关的连接列的统计信息(提供extendedstatistics的功能)。
Dynamic Sampling Levels
动态采样默认为启动状态,可以设置 OPTIMIZER_DYNAMIC_SAMPLING=0来禁用掉这一特性。
OPTIMIZER_DYNAMIC_SAMPLING也是和动态采样最重要的参数,它控制着动态采样级别。
下面用相关实验来加深下大家对动态采样的理解。
1、新建测试数据
新建一张 T_SAMPLE 表
set autotrace off set linesize 200 drop table t_sample purge; create table t_sample as select * from dba_objects; create index idx_t_sample_objid on t_sample(object_id) ; select num_rows, blocks, last_analyzed from user_tables where table_name = 'T_SAMPLE';
这里我们可以发现统计信息没有被收集,对应的 NUM_ROWS,BLOCKS 和 LAST_ANALYZED 都是空的。
2、跟踪执行计划
用 set autotrace on 的方式来跟踪 SOL 的执行计划,如下 :
set autotrace traceonly; select * from t_sample where object_id=20;
注意上面的参数dynamic sampling used for this statement (level=2),这个就是动态采样,当一张表是新建表时, Oracle 只好动态地收集这个表的相关信息。然后等到晚上 10 点,再将其收集到数据字典中。
3、手工收集统计信息
收集统计信息命令如下:
exec dbms_stats.gather_table_stats(ownname => 'SYS', tabname =>'T_SAMPLE', estimate_percent => 10,method_opt=>'for all indexed columns', cascade=>TRUE);
查看相关信息
set autotrace off; select num_rows, blocks, last_analyzed from user_tables where table_name ='T_SAMPLE';
4、再次跟踪执行计划
用 set autotrace on 的方式来跟踪 SOL 的执行计划,如下 :
set autotrace traceonly; select * from t_sample where object_id=20;
这里其实就可以发现dynamic sampling关键字不见了,也就是已经做了统计信息收集。
凡事有利必有弊,动态采样也不是神器。它采样的数据块越多,系统开销就越大,这样会增加SQL硬解析的时间,如果是数据库仓库(DW、OLAP)环境,SQL执行时间相当长,硬解析时间只占整个SQL执行时间的一小部分,那么可以适当的提高动态采样级别,这样是有利于优化器获取更加正确的信息。一般设置为3或4比较合适。
但是在并发比较严重的OLTP系统中,每秒中有成千上万的SQL语句执行,它要求SQL语句短小、执行时间短,所以在OLTP系统中应该减低动态采样级别或不用动态采样。
后面会分享更多DBA方面内容,感兴趣的朋友可以关注下!!