1. 统计信息收集策略
序号 | 收集级别 |
---|---|
1 | 数据库(DB) |
2 | 用户(Schema) |
3 | 对象(Object) |
(2) 收集启用方式
序号 | 启用方式 |
---|---|
1 | 收集启用 |
2 | 收集不启用 |
3 | 不收集 |
即允许数据库库级别设置收集启用,收集不启用或者不收集,也允许Schema级别收集启用,收集不启用或者不收集,还允许对象级别的收集启用,收集不启用或者不收集。同一个数据库中同时设置了以上各个级别的情况下,按照对象级别覆盖用户级别,用户级别覆盖数据库级别的策略进行。
类型 | 优先级 | 是否启用 | 超时是否kill | 超时是否启动? |
---|---|---|---|---|
新建索引 | 1 | 是 | 否 | 是 |
新建表并初始化数据 | 2 | 是 | 否 | 是 |
DML > 10%(不管是否有DDL) | 3 | 根据数据库策略决定 | 是 | 否 |
I) 索引建立时,无论数据库的收集策略启用与否,都必须收集并启用该索引的统计信息,无需cascade表收集。10g及以上的Oracle数据库会自动收集索引统计信息,9i版本的数据库尚不具备该功能,变更时若为9i数据库,则需要通过自动或手动程序来收集。
II) 新建立空表时无需收集统计信息,但新建表并且初始化数据时,无论数据库的收集策略启用与否,都必须收集并启用。
III) 已有表无论是否发生DDL操作,直接按照DML>=10%来判断是否收集启用。对于收集启用的数据库,备份旧统计信息后,收集并启用新的统计信息,收集不启用的数据库,则收集后导回原统计信息,若超过收集窗口,不再启动收集。
本次采样率=Max(1,Min(100,(预期收集时间 * 上次采样率 / 上次收集时间)))
Max (1, Min (100, (15 * 100 / (5*60)))) = 5
2. 统计信息收集方式
开发人员在request系统上报给开发DBA的需要填写的申请表模板:统计信息收集脚本书写申请表.xlsx
开发DBA填写后,反馈给开发人员放到版本中的评估模板:统计信息风险评估模板.xlsx
9i库新建索引收集统计信息模板:9i_crt_gather_index_stats.sql
9i库新建表收集统计信息模板:9i_crt_gather_table_stats.sql
10g库新建表收集统计信息模板:10g_crt_gather_table_stats.sql
11g库新建表收集统计信息模板:11g_crt_gather_table_stats.sql
3. 统计信息处理机制
INSERT INTO stats_schema_config (gather_owner,gather) VALUES('USER1', 'N');
COMMIT;
INSERT INTO dbmgr.stats_schema_config(gather_owner) values('USER1');
INSERT INTO dbmgr.stats_object_config(object_owner, object_type, object_name, gather)
values ('USER1', 'TABLE', 'MY_TABLE', 'N');
COMMIT;
如果数据库的版本是10g及以上,直接通过锁定表的统计信息来实现统计信息不收集的配置即可(9i数据库不支持锁定对象统计信息,需要单独配置)。
INSERT INTO dbmgr.stats_schema_config(gather_owner, gather, gather_dml, stats_enable)
VALUES('USER1', 'Y', 'Y', 'N');
COMMIT;
INSERT INTO dbmgr.stats_schema_config(gather_owner, gather, gather_dml, stats_enable)
values('USER1', 'Y', 'Y', 'N');
INSERT INTO dbmgr.stats_object_config
(object_owner, object_type, object_name, gather, gather_dml, stats_enable)
values('USER1', 'TABLE', 'MY_TABLE', 'Y', 'Y', 'N');
COMMIT;
三 附录
1. 统计信息收集参数配置
参数
|
说明
|
备注
|
ownname
|
属主
|
|
tabname
|
表名
|
|
partname
|
分区名
|
|
estimate_percent
|
采样率,取值为区间 [0.000001,100] 默认值为DBMS_STATS.AUTO_SAMPLE_SIZE, 由Oracle决定合适的采样率。 |
默认取值100%。
如上次成功收集时间超过15分钟,按比例降低采样率。
最低为1%。
本次采样率=max(1,min(100,(预期收集时间 * 上次采样率 / 上次收集时间)))
|
block_sample
|
是否采用随机块采样。 随机块采样性能较好,但准确性不可靠。 随机行采样性能较低,但准确性较高。 默认值为FALSE,采用随机行采样。 |
取值FALSE
|
method_opt
|
直方图建立方式。 格式为FOR ALL [INDEX] COLUMNS [size_clause] size_clause常取如下值: SIZE REPEAT 只在有直方图的列上,创建直方图 SIZE AUTO 由Oracle按数据分布及使用情况决定哪些列要创建直方图 默认值为:FOR ALL COLUMNS SIZE AUTO |
FOR ALL COLUMNS SIZE REPEAT
,首次直方图建立由人工评估、创建
|
degree
|
收集的并行度。 默认值为NULL,表示取CREATE TABLE或ALTER TABLE指定的并行度。 |
分大(>10g)、中(>1g)、小表(<=1g)三级, 各级默认值都为1。可根据需要调整各级并行度。 |
granularity
|
收集粒度。
|
对表为ALL, 对分区为PARTITION, 对有子分区的分区按PARTITION和SUBPARTITION各收集一次。 |
cascade
|
是否收集索引。
|
TRUE
|
stattab
|
统计信息收集后,保存历史统计信息的表。
|
9i
库表名:CBO_STATS_BAK。
10g
库不使用该参数,通过dba_tab_stats_history获得历史统计信息。
|
statid
|
统计信息收集后,保存历史统计信息的记录ID。
|
9i
库:按类型、日期时间及序列,自动生成。
10g
库不使用该参数,通过dba_tab_stats_history获得历史统计信息。
|
statown
|
统计信息收集后,保存历史统计信息的表的属主。
|
9i
库属主:DBMGR。
10g
库不使用该参数,通过dba_tab_stats_history获得历史统计信息。
|
no_invalidate
|
是否使相关游标失效。
|
收集启用为FALSE, 收集不启用为TRUE |
force
|
是否忽略锁定,强制收集。
|
9i
库不支持锁定统计信息,无此参数。
10g
库为FALSE。
|
参数
|
说明
|
备注
|
ownname
|
属主
|
|
tabname
|
表名
|
|
partname
|
分区名
|
|
estimate_percent
|
采样率,取值为区间[0.000001,100] 默认值为DBMS_STATS.AUTO_SAMPLE_SIZE, 由Oracle决定合适的采样率。 |
采用AUTO_SAMPLE_SIZE。
该参数值在11g中可达到之前版本100%采样率的准确性,资源消耗只有之前版本的10%。
|
block_sample
|
是否采用随机块采样。 随机块采样性能较好,但准确性不可靠。 随机行采样性能较低,但准确性较高。 默认值为FALSE,采用随机行采样。 |
取值FALSE
|
method_opt
|
直方图建立方式。 格式为FOR ALL [INDEX] COLUMNS [size_clause] size_clause常取如下值: SIZE REPEAT 只在有直方图的列上,创建直方图 SIZE AUTO 由Oracle按数据分布及使用情况决定哪些列要创建直方图 默认值为:FOR ALL COLUMNS SIZE AUTO |
FOR ALL COLUMNS SIZE REPEAT
,首次直方图建立由人工评估、创建
|
degree
|
收集的并行度。 默认值为NULL,表示取CREATE TABLE或ALTER TABLE指定的并行度。 |
分大(>10g)、中(>1g)、小表(<=1g)三级, 各级默认值都为1。可根据需要调整各级并行度。 |
granularity
|
收集粒度。
|
通过dbms_stats.set_global_prefs或dbms_stats.set_table_prefs设置表的INCREMENTAL为TRUE,PUBLISH为TRUE,取granularity为AUTO
|
cascade
|
是否收集索引。
|
TRUE
|
stattab
|
统计信息收集后,保存历史统计信息的表。
|
不使用。采用dba_tab_stats_history记录历史统计信息。
|
statid
|
统计信息收集后,保存历史统计信息的记录ID。
|
不使用。采用dba_tab_stats_history记录历史统计信息。
|
statown
|
统计信息收集后,保存历史统计信息的表的属主。
|
不使用。采用dba_tab_stats_history记录历史统计信息。
|
no_invalidate
|
是否使相关游标失效。
|
始终收集启用,为FALSE
|
Force
|
是否忽略锁定,强制收集。
|
FALSE
|
2. Oracle系统表的统计信息收集策略
Oracle对象 | 收集策略说明 | 备注 |
---|---|---|
Dictionary统计信息 | 默认收集Dictionary的统计信息信息。 1,使用oracle的自动收集统计信息的job任务来收集,但需要设置prefs: dbms_stats.SET_GLOBAL_PREFS(pname=>'AUTOSTATS_TARGET',pvalue=>'ORACLE'); 2,修改自动收集的缺省的resoure plan 设置为空 exec dbms_scheduler.set_attribute('SYS.MONDAY_WINDOW','RESOURCE_PLAN',''); exec dbms_scheduler.set_attribute('SYS.TUESDAY_WINDOW','RESOURCE_PLAN',''); exec dbms_scheduler.set_attribute('SYS.WEDNESDAY_WINDOW','RESOURCE_PLAN',''); exec dbms_scheduler.set_attribute('SYS.THURSDAY_WINDOW','RESOURCE_PLAN',''); exec dbms_scheduler.set_attribute('SYS.FRIDAY_WINDOW','RESOURCE_PLAN',''); exec dbms_scheduler.set_attribute('SYS.SATURDAY_WINDOW','RESOURCE_PLAN',''); exec dbms_scheduler.set_attribute('SYS.SUNDAY_WINDOW','RESOURCE_PLAN',''); 3,做为11g数据库建库初始化的标准步骤。 | |
Fixed Object统计信息 | 默认收集Fixed Object的统计信息。 通过定时监控: 上一次fix收集的时间 > 数据库创建时间(created_date) + 60天, 即建库后60天还未收集的库,报警出来,由运维dba安排变更,在非工作时间收集。 收集脚本如下: sqlplus '/as sysdba' SQL> alter system set aq_tm_processes = 1 scope = both; SQL> exec dbms_stats.gather_fixed_objects_stats; SQL> alter system set aq_tm_processes = 0 scope = both; | 建立报警机制 |
SYSTEM统计信息 | 默认不收集系统统计信息。 若某些cpu 敏感的sql经过评估需要收集系统统计信息,请发变更,安排在生产典型负载工作时间段收集。 SQL> exec dbms_stats.gather_system_stats(gathering_mode=>'interval',interval=>30); SQL> select * from sys.aux_stats$; --说明:确认flag为0,且SREADTIM,MREADTIM,CPUSPEED和MBRC都存在对应值 |
3. 特殊变更场景下统计信息相关特性
变更步骤 | 表统计信息 | 字段统计信息 | 索引统计信息 |
---|---|---|---|
1、新增空字段,并建立索引 | 不变 | 空 | 新增加的字段没有初始化数据,9i为0,10g及以上时为null) |
2、DML达到收集阀值,收集表统计信息 | 不变 | 最新(Oracle恢复备份统计信息的原则:如果原字段的统计信息为空,则用当前新值覆盖空值,包括0) | 不变 |
3、DML再次达到阀值,收集统计信息 | 不变 | 不变 | 不变 |
场景二:
变更步骤 | 表统计信息 | 字段统计信息 | 索引统计信息 |
---|---|---|---|
1、已有字段新建索引 | 不变 | 不变 | 最新 |
2、DML达到收集阀值,收集表统计信息 | 不变 | 不变 | 不变 |
3、DML再次达到阀值,收集统计信息 | 不变 | 不变 | 不变 |
场景三:
变更步骤 | 表统计信息 | 字段统计信息 | 索引统计信息 |
---|---|---|---|
1、新增字段初始化数据,并建立索引 | 不变 | 最新初始化值 | 最新 |
2、DML达到收集阀值,收集表统计信息 | 不变 | 不变 | 不变 |
3、DML再次达到阀值,收集统计信息 | 不变 | 不变 | 不变 |
数据库版本 | user_tab_modifications | 收集级别 | 变更导致的统计信息变化 | |||
---|---|---|---|---|---|---|
表 | 发生改变的旧分区 | 新分区 | 表 | 分区 | ||
split | 9i/10g | 不变 | 不变 | 无数据 | 无变化 | 被拆分的旧分区, 和拆分出的新分区统计信息都为空 |
数据库(DB) | 数据库(DB) | 数据库(DB) | 11g | delete增加 | delete增加 | |
merge | 9i/10g | 不变 | 清除 | / | 无变化 | Merge后的分区统计信息为空 |
数据库(DB) | 数据库(DB) | 数据库(DB) | 11g | 数据库(DB) | 数据库(DB) | |
add | 9i/10g/11g | 无变化 | / | 无数据 | 无变化 | 新分区统计信息为空 |
drop | 9i | delete增加 | / | / | 无变化 | 保留的分区统计信息不变 |
数据库(DB) | 数据库(DB) | 数据库(DB) | 10g/11g | 不变 |
表 | 索引 | ||||||
---|---|---|---|---|---|---|---|
user_tab_modifications | 统计信息 | created | last_ddl_time | timestamp | last_analyzed | ||
9i | 不变 | 清空 | 不变 | 改变 | 不变 | 清空 | status改变, 索引失效, 需要重建才可使用, 其他无变化 |
10g,11g | 不变 | 不变 | 不变 | 改变 | 不变 | 不变 |
结论:I)9i中做MOVE操作时,先备份统计信息再做MOVE操作,操作完毕后,收集新的统计信息,收集完毕后新的统计信息导出备用,重新导回旧的统计信息。
II)10g,11g做MOVE操作时,可以不处理表的统计信息,系统自动保持不变。
III)由于MOVE会改变索引的状态,要求进行索引索引重建,按照索引重建的方式对应处理。
表 | |||||||
---|---|---|---|---|---|---|---|
操作 | 数据库 版本 | user_tab_modifications | 统计信息 | last_ddl_time | timestamp | created | last_analyzed |
Shrink/ Shrink compact | 9i | 没有shrink功能 | |||||
10g/11g | 不变 | 不变 | 不变 | 不变 | 不变 | 不变 |
表 | 索引 | ||||||
---|---|---|---|---|---|---|---|
user_tab_modifi_ cations | 统计信息 | truncated | last_ddl _time | timestamp | last_ analyzed | 索引新建立 | |
9i,10g | 所有行insert | 空 | YES | 改变 | 改变 | 空 | |
11g | 所有行insert | 空 | NO | 不变 | 不变 | 空 |
版本 | 重定义类型 | 表和索引 | |
---|---|---|---|
9i,10g 11g | 数据重整,结构不变 | 重定义前备份统计信息 | if !supportLists>1) endif>影响分析启用新统计信息可以提高性能时,重定义后,重新收集并启用新的统计信息。 if !supportLists>2) endif>影响分析不确定影响时,为确保稳定,重定义后收集统计信息导出,恢复原表和索引旧的统计信息。 |
分区表转普通表或普通表转分区表 | 无需备份统计信息(因结构变化,实施前备份的统计信息无法恢复,实施后备份的统计信息为空,恢复时会被新收集的统计信息覆盖) | 测试期间,要确定重定义后,表和索引统计信息改变,在新结构下SQL性能确实得到提升,才可以下发版本操作。 |
1) 直接DROP原有索引,然后重新create索引。此类操作方式等价于新建立索引,除非索引的结构变化需要,否则不建议采用删除再新建的方式。这种方式统计信息的策略和新建索引处理一致。
2) 采用REBUILD INDEX的方式,直接重建索引。
由于Rebuild索引不改变索引的结构,因此,除非影响分析确认必须重新启用新的统计信息,否则:重建索引前,备份旧的统计信息,重建索引后,收集新的统计信息,然后恢复旧的统计信息。10g和11g都会自动收集统计信息,因此无需重新编写收集脚本,只需备份新的统计信息,9i要求先收集重建后索引的统计信息,然后备份新统计信息,恢复旧的统计信息。
dba_tab_modifications | 表 | ||||||
---|---|---|---|---|---|---|---|
DML量 | truncated | 统计信息 | last_ddl_time | timestamp | created | last_analyzed | |
9i | 不变 | 改变 | 不变 | 改变 | 不变 | 不变 | 不变 |
10g | 不变 | 改变 | 不变 | 改变 | 不变 | 不变 | 不变 |
11g | delete增加 | 改变 | 不变 | 改变 | 改变 | 不变 | 不变 |
4. 统计信息RBO和CBO的原理简述
1. Hash join
2. 数据仓库中的 star transformation
3. Unnested sub query
4. Push predicate