数据库性能优化是企业IT运维的核心任务,而统计信息(Statistics)作为优化器生成高效执行计划的基础数据,其重要性不言而喻。Oracle数据库从11g版本开始引入自动维护任务框架,其中自动优化器统计信息收集(Auto Optimizer Statistics Collection)任务默认启用,在预定维护窗口内自动收集或更新缺失和陈旧的统计信息。
这一机制的初衷是减轻DBA的工作负担,确保优化器始终拥有最新的数据分布信息。然而,在实际生产环境中,如果自动统计信息收集的时间安排不当,可能会对数据库性能造成严重冲击,导致SQL执行变慢、事务阻塞等问题。
本文将从实际运维角度出发,深入分析Oracle自动统计信息收集的潜在问题,并提供切实可行的解决方案和最佳实践建议。
自动统计收集的潜在问题
1. 时机不当导致性能波动
Oracle默认的自动统计收集安排在每周的维护窗口进行,这些窗口通常设置在夜间或周末。但在实际环境中,如果数据库配置未根据业务特点调整,或者业务具有特殊的高峰时段,统计收集任务可能在不恰当的时间运行。
典型问题场景:
统计收集任务占用大量CPU和I/O资源 与OLTP交易争夺系统资源 导致业务查询响应时间延长 在极端情况下,任务可能运行数小时而非预期的几分钟
统计信息收集本质上需要对表和索引进行扫描,如果在业务高峰期进行,必然会与在线事务产生资源竞争。
2. 统计信息过期或不准确
自动任务仅收集"缺失"或"陈旧"(stale)的统计信息,但"陈旧"的判定存在滞后性:
默认阈值限制:当表中10%以上的行被修改时才标记为需要更新统计 判定滞后:对于数据变化频繁的系统,如果两次收集间隔内数据变动巨大但未达阈值,统计信息可能仍被视为有效 任务失败影响:某些情况下自动任务可能未成功完成统计收集,导致统计信息停留在旧版本
这些问题会导致优化器基于过时数据估算基数(cardinality),从而选择错误的执行计划,表现为查询性能不稳定。
3. 收集过程中的资源争用
自动统计收集使用Oracle内置的并行机制,在大型表上可能并行扫描多个分区或索引:
CPU和I/O争用:如果并行度设置过高且在业务期运行,会大量占用系统带宽 内存压力:收集统计时可能产生大量的PGA内存使用 锁等待:在极端情况下可能对表加锁,引发锁等待或内存争用
4. 任务失败或未运行
自动统计收集任务可能由于各种原因失败:
维护窗口未启用或配置错误 权限问题 统计收集过程中发生系统错误 表空间不足等环境问题
由于自动任务在后台静默运行,管理员可能难以及时发现失败情况,从而埋下性能隐患。
优化自动统计收集的策略
1. 合理安排自动收集的时间窗口
Oracle默认提供7个维护窗口(周一至周日),这些窗口组成维护窗口组(Maintenance Window Group)。
查看当前窗口设置
SELECT window_name, repeat_interval, duration, enabled
FROM dba_scheduler_windows;
调整窗口时间和持续时间
-- 修改周一窗口开始时间为凌晨2点,持续4小时
EXEC DBMS_SCHEDULER.SET_ATTRIBUTE('MONDAY_WINDOW', 'repeat_interval',
'freq=daily;byday=MON;byhour=2;byminute=0;bysecond=0');
EXEC DBMS_SCHEDULER.SET_ATTRIBUTE('MONDAY_WINDOW', 'duration',
numtodsinterval(4, 'hour'));
启用/禁用特定窗口
-- 禁用周日窗口
EXEC DBMS_SCHEDULER.DISABLE('SUNDAY_WINDOW');
-- 重新启用窗口
EXEC DBMS_SCHEDULER.ENABLE('SUNDAY_WINDOW');
调整建议:
将工作日窗口调整到凌晨业务低峰期 适当缩短持续时间以减少对白天业务的影响 根据实际业务模式灵活配置各窗口时间
2. 启用或禁用自动统计收集任务
查看当前任务状态
SELECT client_name, status FROM dba_autotask_client;
禁用自动统计收集
BEGIN
DBMS_AUTO_TASK_ADMIN.disable(
client_name => 'auto optimizer stats collection',
operation => NULL,
window_name => NULL
);
END;
/
重新启用自动统计收集
BEGIN
DBMS_AUTO_TASK_ADMIN.enable(
client_name => 'auto optimizer stats collection',
operation => NULL,
window_name => NULL
);
END;
/
注意事项:
除非有完善的手动统计收集策略,否则不建议长期禁用自动任务 如果确实需要禁用,应制定定期手动收集统计的计划 可以考虑在特定窗口禁用,而在其他窗口保持启用
3. 监控自动统计收集任务的运行状态
查看最近执行历史
SELECT job_info, status, window_start_time, window_end_time
FROM dba_autotask_job_history
WHERE client_name = 'auto optimizer stats collection'
ORDER BY window_start_time DESC;
检查当前正在运行的任务
SELECT client_name, status, last_start_date, last_run_duration
FROM dba_autotask_task
WHERE client_name = 'auto optimizer stats collection';
监控统计信息的新鲜度
SELECT owner, table_name, last_analyzed, stale_stats
FROM dba_tab_statistics
WHERE stale_stats = 'YES'
ORDER BY owner, table_name;
监控要点:
定期检查任务执行状态和耗时 关注失败任务的错误信息 监控统计信息的更新频率和新鲜度 设置告警机制,及时发现异常情况
4. 手动收集统计信息的时机和方法
数据大规模变更后
-- 收集单表统计信息
EXEC DBMS_STATS.GATHER_TABLE_STATS(
owner => 'SCOTT',
table_name => 'EMP',
cascade => TRUE
);
定期全库统计收集
-- 收集整个schema的统计信息
EXEC DBMS_STATS.GATHER_SCHEMA_STATS(
owner => 'APPS',
cascade => TRUE,
degree => 4
);
-- 收集全库统计信息
EXEC DBMS_STATS.GATHER_DATABASE_STATS(
cascade => TRUE,
degree => 4
);
锁定关键统计信息
-- 锁定表统计信息
EXEC DBMS_STATS.LOCK_TABLE_STATS(owner => 'SCOTT', table_name => 'EMP');
-- 解锁表统计信息
EXEC DBMS_STATS.UNLOCK_TABLE_STATS(owner => 'SCOTT', table_name => 'EMP');
手动收集建议:
在数据大批量变更后及时更新统计 选择业务低峰期进行全库统计收集 合理设置并行度,避免过度占用资源 对于数据分布稳定的表,可考虑锁定统计信息
版本差异与最佳实践
Oracle版本演进
10g vs 11g及以后版本
10g:使用调度作业GATHER_STATS_JOB实现,每晚10点开始,持续8小时 **11g+**:引入自动维护任务(AutoTask)框架,细分为7个窗口,算法更智能
12c及以上新特性
在线统计收集功能 并发统计收集(Concurrent Stats Gathering) 更精细的分区统计更新机制
19c长期支持版
任务挂起和继续机制 动态并行度调整 改进的资源管理
通用最佳实践
保持自动统计收集启用
除非特殊原因,不要长期关闭自动任务 自动任务能确保大部分情况下统计信息及时更新 定期审查和调整
定期检查自动任务运行日志和统计信息新鲜度 根据业务变化调整窗口时间和任务配置 结合手动策略
针对关键业务表制定手动收集计划 手动策略应与自动任务互补,避免重复 监控与报警
利用Oracle工具监控自动统计任务状态 设置报警,及时发现任务失败或统计过期 测试和验证
更新统计信息后观察关键SQL的执行计划变化 如出现异常,可使用SQL Plan Baseline等手段稳定计划
典型案例分析
案例一:自动统计收集与批量作业冲突
问题描述: 某公司生产数据库在周一凌晨的批处理作业经常超时,系统负载异常高,部分SQL执行时间比平时多出数倍。
问题分析:
AWR报告显示凌晨2点左右CPU使用率和I/O等待显著升高 自动统计收集任务运行接近4小时才完成 新统计信息导致执行计划变化,在高负载时段反而降低查询效率
解决方案:
调整维护窗口时间:将统计收集窗口从晚上10点推迟到凌晨3点 降低并行度:将并行度从AUTO调整为固定的4并行 手动预收集:对周末批量加载的关键表提前收集统计 监控验证:持续监控任务执行情况和数据库性能
效果:
统计收集任务在预定窗口内顺利完成 批处理作业运行时间恢复正常 系统资源使用更加合理
案例二:自动统计任务失败导致性能下滑
问题描述: 某企业数据库查询性能逐渐变差,重启后暂时恢复,但问题反复出现。
问题分析:
执行计划发生变化,有效的索引扫描被替换为全表扫描 多数表的统计信息停留在一个月前 自动统计收集任务因SYSAUX表空间不足而连续失败
解决方案:
修复环境问题:扩充SYSAUX表空间,清理不必要数据 补收统计信息:手动收集全库统计信息 加强监控:配置任务失败告警,纳入日常巡检 建立备份机制:制定定期手动维护计划
效果:
查询性能恢复正常 执行计划回归预期路径 建立了完善的监控和备份机制

Oracle自动统计信息收集机制是一个强大的工具,但需要正确的配置和管理才能发挥最佳效果。通过本文的分析和建议,数据库管理员可以:
理解潜在风险:认识自动统计收集可能带来的性能问题 掌握配置方法:学会调整维护窗口、启用/禁用任务等操作 建立监控机制:及时发现和处理任务异常 制定最佳实践:结合自动和手动策略,确保统计信息质量
关键在于在自动化与人工干预之间取得平衡:既要充分利用Oracle的自动维护框架,也不能完全依赖自动化而疏于监控。通过合理的配置、持续的监控和适时的人工干预,我们可以确保统计信息始终准确,优化器生成最佳执行计划,从而保障数据库的高效稳定运行。
对于数据库新手而言,建议从以下几个方面入手:
从监控开始:定期检查自动任务的运行状态 逐步调整:根据业务特点调整维护窗口时间 建立流程:制定统计信息维护的标准操作流程 积累经验:通过实践不断优化配置和策略
只有深入理解并正确使用自动统计信息收集机制,才能让这个"双刃剑"真正为数据库性能优化服务。




