分区表prune未生效即查询全分区扫描,主因是where条件未直接、确定地约束分区键,如函数包裹、含计算、非确定性函数或参数化变量,导致优化器无法静态推导目标分区。

分区表 prune 未生效,通常意味着查询没有按预期只扫描目标分区,而是全分区扫描,导致性能下降。核心原因在于 SQL 条件无法被优化器识别为可下推到分区裁剪(partition pruning)的谓词。
WHERE 条件未使用分区键或表达式不可下推
分区裁剪依赖优化器能静态推断出哪些分区可能匹配。如果 WHERE 中的条件不直接、明确地约束分区键,prune 就会失效。
- 分区键是 date_col(类型 DATE),但写成 WHERE date_col >= '2024-01-01' AND date_col ✅ 可裁剪
- 写成 WHERE YEAR(date_col) = 2024 AND MONTH(date_col) = 1 ❌ 函数包裹后无法下推(MySQL/Oracle/StarRocks 等多数引擎均不支持)
- 写成 WHERE date_col + INTERVAL 1 DAY > '2024-01-01' ❌ 表达式含计算,失去确定性
- 分区键是 user_id % 100 这类虚拟列?确保 WHERE 中直接等值匹配该表达式结果,而非原始 user_id
使用了非确定性函数或参数化变量
优化器需在计划生成阶段就确定分区范围。若条件中含 NOW()、RAND()、USER() 或 PREPARE 中的 ? 占位符且未绑定具体值,裁剪常失效。
- WHERE dt = CURDATE():CURDATE() 是非确定性函数,多数引擎(如 MySQL 8.0.23+ 除外)不支持动态裁剪
- WHERE dt = ?:预编译时 ? 无值,优化器无法判断分区 → 执行时才知,但计划已定
- 解决办法:应用层拼接具体日期字符串;或使用存储过程传入确定值后再查
JOIN 或子查询破坏了分区过滤上下文
当分区表参与 JOIN,且驱动表返回结果不确定、或 ON 条件未覆盖分区键时,优化器可能放弃裁剪。
- LEFT JOIN 分区表,但 ON 中分区键条件写在 WHERE(变成隐式 INNER),或条件来自右表字段 → 裁剪失效
- 子查询返回多行/NULL,外层用 IN (SELECT ...) 关联分区键 → 多数引擎无法静态推导分区范围
- 建议:把分区过滤条件尽量放在最外层 WHERE;JOIN 时确保 ON 包含等值分区键,并控制驱动表小且有索引
EXPLAIN 中关键检查项
运行 EXPLAIN FORMAT=TREE(MySQL 8.0+)或 EXPLAIN PARTITIONS(旧版),重点看:
- partitions 列是否只列出几个分区(如 p202401,p202402),而非 NULL 或全部分区名
- 执行计划中是否出现 "Using where; Using filesort" 但没提分区裁剪 → 很可能没生效
- MySQL 8.0+ 的 TREE 输出里找 "partitions: [p202401,p202402]",同时确认该行对应的是你的分区表,不是物化临时表
- 注意 filtered 值极低(如 rows 高 → 可能全分区扫描后靠 WHERE 过滤,而非裁剪










