分区裁剪是否生效,关键看执行计划中是否有PARTITION START和STOP;无则未生效,常见原因包括分区键上使用函数、隐式类型转换、绑定变量未启用bind-aware等。
分区裁剪(Partition Pruning)到底有没有生效?
没生效就等于白分区。oracle 是否真正跳过无关分区,只看执行计划里有没有 partition start 和 partition stop 这两行。没有?说明裁剪失败,查询仍在全表扫描。
常见失效原因包括:
-
WHERE子句中对分区键用了函数,比如TRUNC(create_date)、TO_CHAR(dt, 'YYYY')—— 优化器无法推导出分区边界 - 隐式类型转换,比如把
DATE分区键和字符串字面量直接比较:WHERE dt = '2023-01-01' - 使用了绑定变量但未启用
bind-aware cursor sharing,导致硬解析时无法确定分区范围 - 分区键不在
WHERE条件中,或条件太宽泛(如dt >= DATE '1970-01-01')
验证方式:用 EXPLAIN PLAN FOR SELECT ... 后查 PLAN_TABLE,重点盯 OPERATION 列是否含 PARTITION RANGE SINGLE 或 ITERATOR,再核对 START/STOP 值是否精确到单个分区。
本地索引(Local Index)为什么比全局索引更适合分区表?
本地索引和表分区一一对应,每个分区自带独立索引段。这意味着:
- 分区裁剪后,索引访问也自动限制在目标分区内部,避免跨分区跳转
-
DROP PARTITION或EXCHANGE PARTITION时,对应索引分区自动维护,无需重建全局索引(否则可能锁表数分钟) - 统计信息可按分区收集(启用
INCREMENTAL),大幅缩短DBMS_STATS.GATHER_TABLE_STATS耗时
反例:全局索引虽支持非分区键查询,但一次 UPDATE 或 DELETE 可能触发所有分区索引条目的重写,I/O 放大明显。建本地索引的典型语句是:CREATE INDEX idx_dt ON t(create_date) LOCAL,不带 GLOBAL 关键字。
范围分区(RANGE Partitioning)下,如何避免 MAXVALUE 分区成性能黑洞?
很多团队图省事,在最后一个分区写 VALUES LESS THAN (MAXVALUE),结果新数据全挤进去,这个分区迅速膨胀成“巨无霸”,裁剪失效、备份慢、移动难。
正确做法是提前规划周期性扩展:
- 按月/季度分区时,用间隔分区(
INTERVAL)自动创建后续分区,避免人工漏加 - 若必须手动管理,定期(如每月初)执行:
ALTER TABLE t ADD PARTITION p_202606 VALUES LESS THAN (TO_DATE('2026-06-01', 'YYYY-MM-DD')) - 监控
USER_TAB_PARTITIONS中各分区NUM_ROWS和BLOCKS,发现某分区数据量超均值 3 倍就该预警
特别注意:ADD PARTITION 是 DDL 操作,会短暂阻塞 DML;生产环境建议在低峰期执行,并确认表空间有足够空闲块。
并行查询(Parallel Query)开启后反而变慢?
不是所有分区查询都适合并行。当裁剪后只剩 1–2 个分区、且数据量小于几十万行时,启动并行进程的协调开销可能超过收益。
判断依据:
- 先确认裁剪已生效(见第一个副标题),再看单分区数据量:>100MB 或 >500万行才值得考虑并行
- 用
/*+ PARALLEL(t, 4) */显式指定度数,避免依赖PARALLEL_DEGREE_POLICY=AUTO的不可控行为 - 检查系统资源:
V$PQ_TQSTAT查看并行服务器实际分配与等待情况;V$SESSION_LONGOPS看是否卡在px send阶段
一个容易被忽略的点:PARALLEL 提示对 DML 无效,除非先执行 ALTER SESSION ENABLE PARALLEL DML。否则即使写了 /*+ PARALLEL */,INSERT/UPDATE 仍串行执行。











