分区剪枝失效的典型表现是执行计划中缺失PARTITION START/STOP字段或出现ALL/KEY/ROWID等模糊值,查单日数据却扫描数十分区甚至全表;根本原因是WHERE条件未直写分区键,如函数包裹、隐式转换、条件藏于子查询或OR分支中。
分区剪枝失效的典型表现
执行计划里看不到 partition start 或 partition stop 字段,或者出现 all、key、rowid 这类模糊值,基本说明剪枝没生效。更直观的是:查某一天的数据,却触发了几十个分区的扫描,甚至全表扫描 —— 这不是分区表慢,是它根本没被当成分区表用。
WHERE 条件必须直写分区键,不许套函数
分区键列一旦被函数包裹(比如 TRUNC(create_date)、TO_CHAR(create_date, 'YYYY-MM')),优化器就无法推导出对应分区边界。类型隐式转换也一样危险,例如把 DATE 分区键和字符串 '2025-01-01' 直接比较,Oracle 会悄悄加 TO_DATE(),同样破坏剪枝。
- ✅ 正确写法:
WHERE create_date >= DATE '2025-01-01' AND create_date - ❌ 错误写法:
WHERE TRUNC(create_date) = DATE '2025-01-01'或WHERE create_date = '2025-01-01' - ⚠️ 注意:使用
DATE字面量比TO_DATE()更安全,避免 NLS 设置干扰
本地索引比全局索引更适合分区剪枝场景
本地索引(LOCAL)每个分区自带一个独立索引段,查询时能和分区剪枝联动:先定位分区,再在该分区索引内检索。而全局索引(GLOBAL)跨所有分区,即使只查一个分区,也可能要遍历整个索引树,还容易因分区 DDL(如 DROP PARTITION)导致索引失效需重建。
- 高频按分区键查询 + 范围过滤 → 优先建
LOCAL索引 - 需要按非分区键字段快速点查(如查某个用户所有订单)→ 才考虑
GLOBAL索引,但得接受维护成本 - 建本地索引时不用指定分区名也能自动对齐:
CREATE INDEX idx ON t(col) LOCAL;
统计信息不准会直接误导剪枝决策
优化器依赖统计信息估算各分区数据量,若过期或缺失,可能选错执行路径 —— 比如本该走分区剪枝+索引扫描,结果选了全分区扫描。尤其对 INTERVAL 分区表,新自动创建的分区默认无统计信息。
- 必须定期收集:
EXEC DBMS_STATS.GATHER_TABLE_STATS('SCHEMA_NAME', 'TABLE_NAME', GRANULARITY => 'ALL'); - 启用增量统计(
INCREMENTAL = TRUE)可大幅降低大表收集开销 - 检查是否启用:
SELECT incremental FROM user_tab_partitions WHERE table_name = 'TABLE_NAME';
/*+ OPT_PARAM('_optimizer_use_feedback' 'false') */ 类提示稳定计划 —— 这些细节不处理,分区再漂亮也白搭。











