上述对系统统计数据的多种管理方法使得我们可以灵活应用统计数据,从而让优化器使用与当前系统负载状态相应的统计数据来估算执行计划代价,生成适应当前负载状态的最优的执行计划。 以下是灵活管理系统统计数据的一个例子。
假如我们有一个系统,在白天(8:00 ~ 18:00)是向终端用户开放的业务系统,会有大量用户同时使用该系统进行业务操作;而在晚上(18:00 ~ 8:00),则用于报表系统,将白天的各种业务数据生成报表。显然,这个系统在白天的负载状况是一个 OLTP(在线事物处理)系统,而在晚上则成为一个 OLAP 系统。这两个时间段的负载情况大不相同:白天的负载主要是大量并发的短事务、单个事务涉及少量数据读写;而晚上的负载是数个或者一个涉及大数据量读操作和计算的长事物。为了能是优化器在两种情况下都能获取到语句的最优执行计划,我们需要收集两个时间段下的不同系统统计数据,并安排作业定时将相应统计数据应用到系统中。
第一步:创建统计表

第二步:收集两个时间段下的系统统计数据副本
白天 10:00 运行:

晚上 20:00 运行:

第三步:创建定时作业,在不同时间段应用不同统计数据 每天白天 8:00 应用 OLTP 负载的系统统计数据:

每天晚上 18:00 应用 OLAP 负载的系统统计数据:

完成上述步骤后,优化器就会在不同时段采用不同系统统计数据估算代价。我们可以对比相同 的执行计划,在不同时间段估算出的 IO 和 CPU 代价。
5.1.4 全局参数管理
在管理统计数据时,Oracle 需要遵循特地的规则来实施相关过程,例如对象取样比例、收集统计数据时的查询并行度等等,而这些规则可以通过调用存储过程中由输入参数指定,也可以全局参 数设置设置其默认值。
设置全局参数
设置全局参数的过程是 DBMS_STATS.SET_PARAM。
输入参数:
• PNAME:、PVAL:参见之前解释其中,可以设置的参数包括:
• CASCADE:收集表的统计数据时,是否同时收集表上面索引的统计数据:
o TRUE 为收集索引统计数据;
o FALSE 不收集索引统计数据;
o 默认值为包中自定义常量 DBMS_STATS.AUTO_CASCADE,即由 Oracle 自己判断哪些索引需要收集统计数据;
• DEGREE:收集统计数据时,执行相关语句的并行度,默认值为空,即采用对象本身定
义的并行度;如果指定常量 DBMS_STATS.DEFAULT_DEGREE,则采用系统默认的并行度;
• ESTIMATE_PERCENT:用于估算统计数据的数据记录(或数据块)百分比(0.000001 ~
100)。默认值为常量 DBMS_STATS.AUTO_SAMPLE_SIZE,即由 Oracle 自己选择合适的比例;
提示:如果需要精确地获得统计数据,需要读取表中的所有数据(即估算比例为 100%)。但是对于大表,读取所有数据意味着大量资源的消耗,因此,通过设置合理的估算比例,可以在保证精度 的同时,减少资源的消耗。在自动方式下,Oracle 会根据一定策略初始化和调整估算比例(即采用比),我们会在后面章节中分析这样的策略。
• METHOD_OPT:收集对象统计数据选项。这是一个字符串,其格式为: METHOD_OPT:= FOR ALL [INDEXED | HIDDEN] COLUMNS [size_clause]
FOR COLUMNS [size_clause] COLUMN|ATTRIBUTE [size_clause]
[,COLUMN|ATTRIBUTE [size_clause] … ]
o FOR ALL COLUMNS 是指收集所有字段的统计数据,加上 INDEXED 关键字则是收集所有被索引的字段的统计数据,加上 INDEXED 关键字则是收集所有被索引的字段的统计数据,加上 HIDDEN 关键字则是收集所有隐藏字段的统计数据;
o FOR COLUMNS 则是为收集指定的一个或多个字段(11g 中还可以是扩展字段:字段组、表达式或者扩展名)收集统计数据;
而如果提供的是扩展字段,而该扩展字段还未被创建,则会创建一个新的扩展字段。 关于扩展统计数据,我们会在下一节具体介绍。
其中,size_clause 子句的格式为:
size_clause := SIZE [integer | auto | skewonly | repeat],
SIZE 指定了收集字段柱状图数据的“桶”的数量。
具体数字(1~254)就是指定柱状图分组(“桶”)具体数量,默认为 75;
auto 则是由 Oracle 根据内部算法自动设置“桶”的数量;
skewonly 则只收集数据分布不均匀的字读的统计数据;repeat 则重复收集已经有柱状图数据的字段;
默认值是:FOR ALL COLUMNS SIZE AUTO.
• NO_INVALIDATE:是否禁止使与对象相关的游标失效;参数值可以为:
o FALSE 会使依赖于对象的游标立即失效;
o TRUE 不会让依赖于对象的游标立即失效,直到该游标被 Oracle 从系统中清除出去;
o 默认值为 DBMS_STATS.AUTO_INVALIDATE,即由 Oracle 自己判断何时使依赖于对象的游标立即失效;
• GRANULARITY:统计数据的粒度,这一参数仅对分区对象有效;参数值可以为:
o AUTO:由存储过程自己决定粒度,这是默认值;
o ALL:收集所有级别(全局、分区、子分区)的统计数据;
o GLOBAL:收集全局统计数据;
o PARTITION:收集分区级别的统计数据;
o SUBPARTITION:收集子分区级别的统计数据;
o GLOBAL AND PARTITION:分别收集全局和分区级别的统计数据;
o APPROX_GLOBAL AND PARTITION:如果过程参数中指定了分区,收集分区级别的统计数据,再由由分区统计数据计算出全局的统计数据(除字段的唯一值数和索引的 唯一键值数外);如果过程参数中没有指定分区,则收集全局统计数据;
• AUTOSTATS_TARGET:自动收集统计数据时,收集哪些对象的数据。这一参数仅在进行 自动收集时有效。参数值可以为:
o ALL:收集系统中所有对象的统计数据;
o ORACLE:收集所有 Oracle 系统用户的对象的统计数据;
o AUTO:由 Oracle 自己决定收集哪些对象的统计数据;
示例:

获取全局参数值
调用函数 DBMS_STATS.GET_PARAM 可以读取当前全局参数的数值。
输入参数:
• PNAME:参见之前解释; 示例:

重置全局参数
调用过程 DBMS_STATS.RESET_PARAM_DEFAULTS 可以将所有参数重置为默认值。
5.1.5 项管理
在 11g 中,由于一些新的功能的加入,引入了一些新参数,这些参数以及原有的全局参数在
11g 中被称为全局选项。并且不再推荐使用全局参数相关的过程管理全局选项(尽管这些函数、过程仍然有效),而是引入了一套新的函数、过程。而 11g 中,每个表还可以有自己的选项设置。
11g 中新增加了以下几个选项:
• PUBLISH:是否立即将新收集到的统计数据发布出来,默认值为 TRUE。在 11g 之前, 如果不是收集副本数据到统计表中,统计收据收集到以后会立即被发布出来(即立刻写入相关数据字典中),优化器再做执行计划优化时,就会采用新的统计数据。而 11g 之后,用户可以让收集到的统计数据成为待定(Pending)状态,经过测试、认为安全以后再发布。
• INCREMENTAL:这是针对分区对象的选项。它决定在维护分区对象(增加、删除分区) 的全局统计数据时,是否是增量进行的,即是否进行全部扫描收集数据,默认值为
FALSE。当满足以下三个条件时,分区对象在分区发生变化时,Oracle 仅扫描变动的分区而非全表来维护全局统计数据:
1、分区表的 INCREMENTAL 选项为 TRUE;
2、分区表的 PUBLISH 选项为 TRUE;
3、收集表的统计数据时,指定了 ESTIMATE_PERCENT 选项为
DBMS_STATS.AUTO_SAMPLE_SIZE;
提示:在 11g 中,出现了一种新分区:INTERVAL Partition Table。当其数据增长时,Oracle 会根据用户设置自动增加分区。对于这种分区表的统计数据的维护,INCREMENTAL 是一个不错的选项。
• STALE_PERCENT:陈旧数据百分比,默认值为 10。在由 Oracle 自己决定是否重新收集某张表的统计数据时,已有数据是否是“陈旧”数据是一个重要的决定因素。而已有统计数据是否陈旧,则是由该表上面的发生变化的数据比例所决定。陈旧数据百分比就是这个判断值。实际上,统计数据陈旧的判断是 11g 之前就存在的,只是这个比例判读值是 Oracle 自己决定、而不能由用户设置。
提示:表的数据自最后一次统计数据收集以来发生的变化可以由视图
DBA/ALL/USER_TAB_MODIFICATIONS 查询得到。
设置选项
针对不同选项级别,有多个过程用于选项设置。
过程 DBMS_STATS.SET_GLOBAL_PREFS 用于设置全局选项数值。输入参数:
• PNAME、PVAL:参见之前解释;
其中,10g 中的全局参数都可以由该过程设置。
过程 DBMS_STATS.SET_DATABSE_PREFS 用于设置数据库中所有表的选项数值。输入参数:
• PNAME、PVAL:参见之前解释;
• ADD_SYS:是否设置 Oracle 系统用户的表的选项,默认为 FALSE;
过程 DBMS_STATS.SET_SCHEMA_PREFS 用于设置数据库中某个用户的表的选项数值。输入参数:
• OWNNAME:需要设置的选项的用户;
• PNAME、PVAL:参见之前解释;
过程 DBMS_STATS.SET_TABLE_PREFS 用于设置数据库中某个用户的表的选项数值。输入参数:
• OWNNAME:需要设置的选项的用户;
• TABNAME:需要设置的选项的表名;
• PNAME、PVAL:参见之前解释;
示例:

获取选项值
调用函数 DBMS_STATS.GET_PREFS 可以读取当前全局或者表的选项数值。
输入参数:
• PNAME:参见之前解释;
• OWNNAME:需要读取选项的表的所有者,默认为 NULL,如果指定了 TABNAME,则为当前用户;
• TABNAME:需要读取选项的表名,默认为 NULL,即读取全局选项;
示例:

导出表选项
针对不同选项级别,有多个过程用于导出表的选项设置到统计表中。
过程 DBMS_STATS.EXPORT_DATABSE_PREFS 用于导出数据库中所有表的选项数值。输入参数:
• STATTAB、STATID、STATOWN、ADD_SYS:参见之前解释;
过程 DBMS_STATS.EXPORT_SCHEMA_PREFS 用于导出数据库中某个用户的表的选项数值。输入参数:
• OWNNAME、STATTAB、STATID、STATOWN:参见之前解释;
过程 DBMS_STATS.EXPORT_TABLE_PREFS 用于导出数据库中某个用户的表的选项数值。输入参数:
• OWNNAME、TABNAME、STATTAB、STATID、STATOWN:参见之前解释;
示例:

导入表选项
针对不同选项级别,有多个过程用于从统计表中导入表的选项设置到。
过程 DBMS_STATS.IMPORT_DATABSE_PREFS 用于导入数据库中所有表的选项数值。
输入参数:
• STATTAB、STATID、STATOWN、ADD_SYS:参见之前解释;
过程 DBMS_STATS.IMPORT_SCHEMA_PREFS 用于导入数据库中某个用户的表的选项数值。输入参数:
• OWNNAME、STATTAB、STATID、STATOWN:参见之前解释;
过程 DBMS_STATS.IMPORT_TABLE_PREFS 用于导入数据库中某个用户的表的选项数值。输入参数:
• OWNNAME、TABNAME、STATTAB、STATID、STATOWN:参见之前解释; 示例:
删除表选项
针对不同选项级别,有多个过程用于删除表的选项设置。
过程 DBMS_STATS.DELETE_DATABSE_PREFS 用于删除数据库中所有表的选项数值。输入参数:
• PNAME、 ADD_SYS:参见之前解释;
过程 DBMS_STATS.DELETE_SCHEMA_PREFS 用于删除数据库中某个用户的表的选项数值。输入参数:
• OWNNAME、PNAME:参见之前解释;
过程 DBMS_STATS.DELETE_TABLE_PREFS 用于删除数据库中某个用户的表的选项数值。输入参数:
• OWNNAME、TABNAME、PNAME:参见之前解释;
示例:
重置全局选项
调用过程 DBMS_STATS.RESET_GLOBAL_PREF_DEFAULTS 可以将所有选项重置为默认值。




