Oracle 19c分区表不支持实时统计信息,唯一可行的“伪实时”方案是显式启用并验证INCREMENTAL=TRUE模式。该模式复用已有分区统计,仅重采新增/变更分区并推导全局统计,需手动配置、验证执行路径及结果,自动任务默认不启用增量逻辑。

Oracle 19c 分区表不支持实时统计信息(Real-Time Statistics),所谓“高效增量”只能靠 INCREMENTAL 模式 + 精准粒度控制实现,不是自动的,必须显式启用并验证。
为什么 INCREMENTAL = TRUE 是分区表统计“伪实时”的唯一可行路径
非分区表可用 REALTIME_STATS(仅 Exadata),但分区表完全被排除在外——DBA_TAB_COL_STATISTICS.NOTES 字段永远为空,SCOPE 永远是 GLOBAL 或 GLOBAL AND PARTITIONED。此时唯一能避免全表重扫的机制就是 INCREMENTAL 模式:它让 Oracle 复用已有分区统计,只对新增/变更分区重新采样,并推导全局统计。
- 必须提前开启:
DBMS_STATS.SET_TABLE_PREFS(ownname => 'SCOTT', tabname => 'SALES', pname => 'INCREMENTAL', pvalue => 'TRUE') - 依赖
ESTIMATE_PERCENT为DBMS_STATS.AUTO_SAMPLE_SIZE(默认),否则可能跳过增量逻辑 - 开启后首次全量收集会生成
SYSAUX中的汇总表(如WRI$_OPTSTAT_HISTGRM_HISTORY),后续才真正生效 - 检查是否生效:
SELECT DBMS_STATS.GET_PREFS('incremental', 'SCOTT', 'SALES') FROM DUAL返回TRUE
如何验证 INCREMENTAL 是否真正在工作
很多人设了 INCREMENTAL => TRUE 就以为万事大吉,但实际执行时 Oracle 可能因各种原因退回到全量模式。关键看三处:
- 执行后查
DBA_TAB_STATISTICS:若GLOBAL_STATS = 'NO'且PARTITION_STATS = 'YES',说明增量已触发 - 对比
DBA_TAB_PARTITIONS.NUM_ROWS和DBA_TABLES.NUM_ROWS:增量成功时,只有新分区的NUM_ROWS更新,而DBA_TABLES.NUM_ROWS应同步更新(由汇总逻辑推导) - 查看
V$SQL中最近的GATHER_TABLE_STATS调用,SQL_TEXT是否含granularity="APPROX_GLOBAL AND PARTITION"—— 这是增量模式的典型执行路径
高频自动任务(AUTO_TASK)对分区表无效,别指望它“自动增量”
DBMS_STATS.SET_GLOBAL_PREFS('AUTO_TASK_STATUS', 'ON') 只控制默认每 15 分钟运行一次的后台任务开关,但它对分区表的行为和普通 GATHER_TABLE_STATS 完全一致:不会启用 INCREMENTAL,也不会跳过未变更分区。它只是定时调用标准收集流程。
- 自动任务默认使用
GRANULARITY => 'AUTO',在分区表上等价于'GLOBAL AND PARTITION',即全分区扫描 - 若你启用了
INCREMENTAL,自动任务仍不会利用它——必须手动触发或写调度脚本 - 检查自动任务是否真在跑:
SELECT ORIGIN, STATUS, COMPLETED FROM DBA_AUTO_STAT_EXECUTIONS WHERE ORIGIN = 'AUTO_TASK' ORDER BY START_TIME DESC,但别误读COMPLETED为“增量完成”
最稳妥的增量收集操作链(带防错)
生产环境不能赌 Oracle 的自动推导,要主动控制范围、验证结果、留回滚余地:
- 先锁定目标分区:
SELECT PARTITION_NAME FROM DBA_TAB_PARTITIONS WHERE TABLE_NAME = 'SALES' AND HIGH_VALUE LIKE '%2026%' AND NUM_ROWS = 0(找空分区或刚插入数据的) - 单分区收集(强制走增量路径):
EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT', tabname => 'SALES', partname => 'SALES_Q3_2026', granularity => 'PARTITION', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE) - 立即刷新全局统计(避免 optimizer 用旧值):
EXEC DBMS_STATS.LOCK_TABLE_STATS('SCOTT', 'SALES'); EXEC DBMS_STATS.UNLOCK_TABLE_STATS('SCOTT', 'SALES');—— 这个 trick 会强制 Oracle 重新合成全局NUM_ROWS - 验证:
SELECT TABLE_NAME, NUM_ROWS, LAST_ANALYZED FROM DBA_TABLES WHERE TABLE_NAME = 'SALES'; SELECT PARTITION_NAME, NUM_ROWS, LAST_ANALYZED FROM DBA_TAB_PARTITIONS WHERE TABLE_NAME = 'SALES' AND PARTITION_NAME IN ('SALES_Q3_2026');
增量不是银弹,SYSAUX 空间增长、首次启用后的冷启动延迟、以及 method_opt 中直方图策略(如 SIZE SKEWONLY)可能破坏增量逻辑——这些细节一旦忽略,收集出来的统计信息反而会让执行计划更差。


















