分区级统计信息仅在大表按时间/范围频繁裁剪且分区数据倾斜超5倍时有效,盲目启用反致优化器误判;需配合auto直方图、分区索引统计及历史分区锁定策略。
分区级统计信息不是“开了就灵”的开关,它只在特定场景下真正起效——比如大表按时间/范围频繁裁剪、且各分区数据分布严重不均时。盲目开启反而可能让优化器误判连接基数。
什么时候该用分区级统计信息
核心判断依据是:查询是否经常通过分区键做精确或范围裁剪(如 WHERE order_date BETWEEN '2025-01-01' AND '2025-03-31'),且不同分区间行数或数据倾斜度差异超过 5 倍以上。
- 典型适用场景:按月/按日分区的订单表、日志表、交易流水表
- 明显不适用:哈希分区表(各分区天然均匀)、LIST 分区中值域固定且数据量稳定的维度表
- 风险点:如果表只有 2–3 个分区,或所有分区行数标准差 DBMS_STATS 在估算跨分区连接时可能因局部统计叠加失真
如何启用并验证增量收集是否生效
Oracle 12c 默认不自动收集分区级统计,必须显式开启 INCREMENTAL 模式,并确保全局参数一致:
- 先设置表级偏好:
DBMS_STATS.SET_TABLE_PREFS('SCHEMA', 'SALES', 'INCREMENTAL', 'TRUE') - 再执行收集:
DBMS_STATS.GATHER_TABLE_STATS('SCHEMA', 'SALES', GRANULARITY => 'AUTO')—— 注意这里必须用AUTO,否则即使设了INCREMENTAL也只收全局统计 - 验证是否启用成功:
SELECT INCREMENTAL, STALE_STATS FROM DBA_TAB_STATISTICS WHERE TABLE_NAME = 'SALES',INCREMENTAL列应为YES - 检查分区统计是否真实存在:
SELECT PARTITION_NAME, NUM_ROWS FROM DBA_TAB_STATISTICS WHERE TABLE_NAME = 'SALES' AND OBJECT_TYPE = 'PARTITION'
直方图和索引统计不会自动继承到分区级
这是最容易被忽略的陷阱:INCREMENTAL 只影响表和列的基础统计(NUM_ROWS、AVG_ROW_LEN 等),但直方图、索引统计、列级 DENSITY 仍需单独处理。
- 直方图必须显式指定:
DBMS_STATS.GATHER_TABLE_STATS(..., METHOD_OPT => 'FOR ALL COLUMNS SIZE AUTO', GRANULARITY => 'AUTO'),且SIZE AUTO才会为每个分区独立生成直方图 - 索引统计默认不按分区收集,除非索引本身是分区索引(
LOCAL)且你调用GATHER_INDEX_STATS并传入GRANULARITY => 'ALL' - 常见错误现象:
EXPLAIN PLAN显示分区裁剪正确,但连接顺序错误 —— 很可能是连接列缺少分区级直方图,导致基数估算偏差超 10 倍
锁住统计前务必确认分区数据稳定性
对活跃分区(如当前月分区)锁统计是危险操作:一旦后续插入大量新数据,优化器仍用旧统计,计划立即劣化。
- 安全做法:只锁历史归档分区(如
P_202412),且确保该分区READ ONLY - 若必须锁活跃分区,需配合动态采样:
OPTIMIZER_DYNAMIC_SAMPLING = 11,让优化器在硬解析时对未锁分区临时补采样 - 检查锁状态:
SELECT STATTYPE_LOCKED FROM DBA_TAB_STATISTICS WHERE TABLE_NAME = 'SALES' AND PARTITION_NAME = 'P_202506',返回ALL表示已全锁
分区级统计真正的价值不在“更细”,而在“更准”——但它要求你清楚知道哪几个分区的数据特征发生了偏移,而不是把所有分区都塞进同一个收集脚本里跑一遍。











