Oracle 优化器统计信息管理

Oracle 优化器统计信息管理

适用版本:Oracle Database 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07


1. 概述

优化器统计信息管理[1]:

关键

  • 准确
  • 及时
  • 稳定

详细见:Oracle 直方图与统计信息


2. 收集策略

2.1 自动收集

SELECT * FROM dba_autotask_client
WHERE client_name = 'auto optimizer stats collection';

-- 默认夜间窗口

2.2 手动收集

-- 表
EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT', 'EMPLOYEES',
  estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
  method_opt => 'FOR ALL COLUMNS SIZE AUTO',
  cascade => TRUE,
  degree => 4);

-- Schema
EXEC DBMS_STATS.GATHER_SCHEMA_STATS('SCOTT',
  estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
  cascade => TRUE,
  degree => 4);

-- 数据库
EXEC DBMS_STATS.GATHER_DATABASE_STATS;

3. 偏好设置

3.1 表级

EXEC DBMS_STATS.SET_TABLE_PREFS('SCOTT', 'EMPLOYEES', 
  'METHOD_OPT', 'FOR ALL COLUMNS SIZE 254');

EXEC DBMS_STATS.SET_TABLE_PREFS('SCOTT', 'EMPLOYEES', 
  'ESTIMATE_PERCENT', 'DBMS_STATS.AUTO_SAMPLE_SIZE');

EXEC DBMS_STATS.SET_TABLE_PREFS('SCOTT', 'EMPLOYEES', 
  'CASCADE', 'TRUE');

EXEC DBMS_STATS.SET_TABLE_PREFS('SCOTT', 'EMPLOYEES', 
  'DEGREE', '4');

3.2 Schema 级

EXEC DBMS_STATS.SET_SCHEMA_PREFS('SCOTT', 'INCREMENTAL', 'TRUE');

3.3 全局

EXEC DBMS_STATS.SET_GLOBAL_PREFS('ESTIMATE_PERCENT', 'DBMS_STATS.AUTO_SAMPLE_SIZE');

3.4 查看

SELECT * FROM dba_tab_stat_prefs WHERE table_name = 'EMPLOYEES';

4. 增量统计

4.1 12c+

-- 启用
EXEC DBMS_STATS.SET_TABLE_PREFS('SCOTT', 'SALES', 'INCREMENTAL', 'TRUE');

-- 仅变化分区
EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT', 'SALES');

4.2 优势

  • 大表快速
  • 仅变化分区

5. Pending 统计

5.1 启用

-- 表
EXEC DBMS_STATS.SET_TABLE_PREFS('SCOTT', 'EMPLOYEES', 'PUBLISH', 'FALSE');

-- 收集到 pending
EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT', 'EMPLOYEES');

5.2 测试

ALTER SESSION SET optimizer_use_pending_statistics = TRUE;
-- 测试 SQL

5.3 发布

EXEC DBMS_STATS.PUBLISH_PENDING_STATS('SCOTT', 'EMPLOYEES');

5.4 删除

EXEC DBMS_STATS.DELETE_PENDING_STATS('SCOTT', 'EMPLOYEES');

6. 锁定统计

6.1 锁定

EXEC DBMS_STATS.LOCK_TABLE_STATS('SCOTT', 'EMPLOYEES');
EXEC DBMS_STATS.LOCK_SCHEMA_STATS('SCOTT');

6.2 解锁

EXEC DBMS_STATS.UNLOCK_TABLE_STATS('SCOTT', 'EMPLOYEES');

6.3 应用

  • 关键表稳定计划
  • 防止自动任务影响

7. 备份恢复

7.1 创建表

EXEC DBMS_STATS.CREATE_STAT_TABLE('SCOTT', 'STAT_BACKUP');

7.2 导出

EXEC DBMS_STATS.EXPORT_TABLE_STATS('SCOTT', 'EMPLOYEES', NULL, 'STAT_BACKUP');

7.3 导入

EXEC DBMS_STATS.IMPORT_TABLE_STATS('SCOTT', 'EMPLOYEES', NULL, 'STAT_BACKUP');

7.4 恢复

-- 恢复到历史时间
EXEC DBMS_STATS.RESTORE_TABLE_STATS('SCOTT', 'EMPLOYEES', 
  sysdate - 1/24);  -- 1 小时前

8. 直方图

8.1 类型

类型适用
FREQUENCYNDV < 254
HEIGHT BALANCEDNDV >= 254
TOP-FREQUENCY高频值(12c+)
HYBRID通用(12c+)

8.2 创建

EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT', 'EMPLOYEES',
  method_opt => 'FOR COLUMNS dept_id SIZE 254');

8.3 查看

SELECT 
  column_name, 
  histogram, 
  num_buckets
FROM user_tab_col_statistics
WHERE table_name = 'EMPLOYEES';

9. 动态采样

9.1 启用

ALTER SESSION SET optimizer_dynamic_sampling = 2;
-- 0-11

9.2 HINT

SELECT /*+ DYNAMIC_SAMPLING(e 4) */ * FROM employees e WHERE ...;

9.3 适用

  • 临时表
  • 缺失统计
  • 复杂查询

10. 监控

10.1 统计状态

SELECT 
  table_name,
  num_rows,
  last_analyzed,
  stale_stats
FROM user_tab_statistics;

10.2 Stale 检查

SELECT table_name, stale_stats 
FROM user_tab_statistics 
WHERE stale_stats = 'YES';

10.3 历史

SELECT * FROM dba_optstat_operations;

11. 常见坑与排错

11.1 CBO 选错计划

-- 1. 检查统计
SELECT last_analyzed, num_rows FROM user_tables WHERE ...;

-- 2. 收集
EXEC DBMS_STATS.GATHER_TABLE_STATS(...);

-- 3. 直方图

11.2 统计过期

-- 1. 自动收集
-- 2. 手动收集
-- 3. 监控 stale

11.3 数据倾斜

-- 直方图
method_opt => 'FOR COLUMNS col SIZE 254'

12. 最佳实践

  1. 自动收集:基础
  2. 大表 AUTO_SAMPLE:平衡
  3. 倾斜列直方图:精准
  4. 增量统计:分区大表
  5. Pending 测试:稳定
  6. 锁定关键表:稳定
  7. 备份统计:回滚
  8. 监控 stale:及时
  9. 动态采样补充:临时
  10. 定期复审:调整

13. 参考资料

[1] Oracle Database SQL Tuning Guide 19c, “Optimizer Statistics” https://docs.oracle.com/en/database/oracle/oracle-database/19/tgsql/optimizer-statistics.html