执行计划未走分区裁剪,首要检查PARTITION RANGE操作符是否出现;若缺失,则说明优化器根本未考虑裁剪,常见原因包括分区键使用函数、隐式转换、绑定变量值不可见、统计信息缺失或动态采样级别过低(≤2)。
执行计划没走分区裁剪,先看 PARTITION RANGE 操作符是否出现
如果 explain plan 或 dbms_xplan.display_cursor 输出里压根没出现 partition range single、partition range iterator 或类似带 partition 的操作符,说明优化器根本没考虑分区裁剪——不是“裁剪错了”,而是“没裁”。常见原因有:
- 查询条件中分区键列用了函数或表达式,比如
WHERE trunc(part_key) = date '2025-01-01',会阻断裁剪 - 分区键列被隐式转换,如
WHERE part_key = '202501'(而实际是NUMBER类型),导致无法匹配分区边界 - 使用了绑定变量,但变量值在硬解析时不可见,CBO 只能按“最保守”方式处理——全分区扫描
- 表或分区未收集统计信息,且动态采样级别太低(如
dynamic_sampling = 1),CBO 缺乏分区数据分布认知
dynamic_sampling 级别太低会导致分区裁剪失效
动态采样在无统计信息时“临时补位”,但它对分区裁剪的支持很有限。Level 2 及以下只采样基表头部块,不识别分区结构;Level 4 才开始跨分区抽样,Level 6+ 才可能推导出有效分区边界。若你看到执行计划里 Rows 预估严重失真(比如预估 1 行,实际扫百万行),且 NOTE 区显示 dynamic sampling used for this statement (level=2),基本可判定采样不足。
临时验证:加 hint 强制 Level 6 再看计划
SELECT /*+ dynamic_sampling(t 6) */ * FROM sales_part t WHERE sale_date = DATE '2025-03-01';
若此时出现 PARTITION RANGE SINGLE,就坐实是动态采样级别问题。生产环境应优先补全统计信息:DBMS_STATS.GATHER_TABLE_STATS 带 GRANULARITY => 'PARTITION' 参数。
绑定变量让 CBO 无法判断具体落在哪个分区
这是最隐蔽也最常见的原因。当 SQL 使用绑定变量(如 WHERE part_key = :p_key),而该变量值在硬解析时刻未知,CBO 就无法确定目标分区。它只能退化为“所有分区都可能命中”,于是生成全分区扫描计划。即使后续每次执行都传入同一值,只要 child cursor 没复用(比如因 bind_mismatch),就反复硬解析。
排查方法:
- 查
v$sql中对应 SQL 的IS_BIND_SENSITIVE、IS_BIND_AWARE、IS_SHAREABLE字段,三者若非全为Y,说明绑定变量未触发自适应游标共享(ACS) - 执行
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('sql_id', NULL, 'ALLSTATS LAST')),看A-Rows是否远大于E-Rows,且Partition Start/Stop显示KEY或ROW LOCATION—— 这代表运行时才决定分区,计划阶段无法裁剪 - 对比字面量写法:
WHERE part_key = 202503,若此时计划立刻出现PARTITION RANGE SINGLE,即可确认是绑定变量导致
分区键类型与绑定变量类型不一致引发隐式转换
哪怕你写了 :p_key,如果应用层传入的是字符串(如 Java 的 String),而分区键是 NUMBER 或 DATE,Oracle 会在内部做隐式转换:TO_NUMBER(:p_key)。这个函数包裹直接杀死分区裁剪——和写 WHERE TO_NUMBER(part_key) = :p_key 效果一样。
验证方式:
- 查
v$sql_plan中对应 SQL 的FILTER_PREDICATES列,若看到TO_NUMBER("PART_KEY")=:P_KEY,就是它 - 在应用侧确保绑定变量类型与列定义严格一致:NUMBER 键就传整数,DATE 键就传
java.time.LocalDate并用setDate() - 避免用字符串拼接构造分区键条件,尤其不要把日期转成
'202503'后再绑定
分区裁剪失败往往不是单一原因,而是动态采样缺失 + 绑定变量类型错配 + 统计信息陈旧三者叠加。最稳妥的做法是:补全带分区粒度的统计信息,关闭 cursor_sharing(设为 exact),并在应用层严格控制绑定变量类型。否则,光调 dynamic_sampling 级别只是治标。


















