PARTITION RANGE ALL 表示分区裁剪失效,即优化器未推导出可跳过的分区边界;典型表现为pstart/pstop显示ALL而非具体数字,主因是WHERE条件中分区键被函数包裹、隐式转换或未直写裸列。
执行计划里出现 PARTITION RANGE ALL 就说明裁剪没生效
这不是 oracle “没能力裁剪”,而是它根本没推导出可跳过的分区边界。最直接的证据就是执行计划中 partition range all 或 pstart/pstop 显示为 all,而不是具体数字或 single。哪怕你只查一天数据,只要看到这个,就等于全分区扫描已启动。
别急着调优 SQL 或重建索引,先确认三件事:
- 用
SELECT partitioning_type, partition_key_columns FROM dba_part_tables WHERE table_name = 'YOUR_TABLE_NAME'查分区键名和类型,注意大小写、下划线、拼写是否和 SQL 中完全一致 - 执行
EXPLAIN PLAN FOR ...后查PLAN_TABLE,重点盯PARTITION_START和PARTITION_STOP列 —— 空值或KEY/ROW LOCATION都算失败 - 确认查询里 WHERE 条件是否直写分区键,比如
WHERE create_date = DATE '2026-06-01'是 OK 的,但WHERE TRUNC(create_date) = DATE '2026-06-01'就直接废掉裁剪
WHERE 条件里用了函数或隐式转换,裁剪立刻失效
Oracle 不会为你“猜”函数背后的分区意图。只要分区键被任何函数包裹(TRUNC()、TO_CHAR()、DATE()),或者和字符串/数字做隐式比较(比如 create_date = '2026-06-01'),优化器就放弃推导分区边界。
典型陷阱:
-
WHERE TO_CHAR(create_date, 'YYYY-MM') = '2026-06'→ 函数禁用裁剪 -
WHERE create_date = '2026-06-01'→ 字符串隐式转 DATE,触发TO_DATE(),同样失效 -
WHERE create_date BETWEEN SYSDATE - 7 AND SYSDATE→ 绑定变量未启用bind-aware时,可能无法稳定裁剪
正确写法只有两种:显式日期字面量(DATE '2026-06-01')或绑定变量配合 DATE 类型传参。
多表 JOIN 时,分区裁剪不会自动“传染”
左表裁剪成功 ≠ 右表也跳过无关分区。JOIN 条件必须让优化器能对右表也推导出分区边界,否则右表仍扫全分区。
关键约束:
- JOIN 条件里必须是裸列等值匹配:
t1.create_date = t2.create_date,不能加TRUNC()或+ INTERVAL 1 DAY - 两张表的分区键字段名、数据类型必须严格一致 ——
DATEvsTIMESTAMP、create_dtvscreate_date都会导致裁剪链断裂 - 如果右表是 RANGE 分区且需时间重叠匹配(如
valid_from/valid_until),JOIN 条件得写成t1.create_date BETWEEN t2.valid_from AND t2.valid_until,且t2上要有(valid_from, valid_until)复合索引
分区键没进主键或唯一约束,建表就埋了雷
Oracle 要求 RANGE 分区表的主键或唯一约束必须包含分区键。如果建表时漏了,虽然能建成功,但后续 DML 或某些查询路径可能触发异常行为,甚至让优化器绕过分区逻辑。
例如:
- 表按
created_timeRANGE 分区,但主键只设id→ 建表会报ORA-14038(除非加ENABLE NOVALIDATE,但这不是合规解法) - 正确做法是主键改为
(id, created_time),或至少加唯一约束含created_time - 分区键若选错(比如用
assigned_user_id),即使语法通过,业务查“近一周工单”也无法触发裁剪,表空间冷热分离也就失去意义
真正起作用的从来不是“分了几个区”,而是 WHERE 里那行裸露的、类型匹配的、没被函数包裹的分区键条件 —— 其他都是配套动作。


















