分区边界值必须严格对齐查询条件且类型精度一致,如date分区用'yyyy-mm-dd'格式;where中需用常量范围谓词,避免函数、变量或非确定性函数包裹分区键。

分区表的边界值设计直接影响查询能否有效剪枝(prune),进而决定扫描数据量和执行效率。核心原则是:边界必须严格对齐查询条件,且分区键表达式需与 WHERE 中的谓词可等价推导。
边界值必须覆盖所有可能的查询输入,且不重叠、无间隙
例如按 DATE 列做范围分区,使用 PARTITION p202401 VALUES LESS THAN ('2024-02-01') 是安全的;若写成 LESS THAN ('2024-02-01 00:00:00') 而列类型为 DATE(无时分秒),MySQL 可能因隐式类型转换导致剪枝失败。边界值应与分区键的数据类型和精度完全一致。
- 整型分区:用整数边界,避免浮点或字符串形式
- 日期分区:统一用
DATE字面量(如'2024-01-01'),不要混用DATETIME或带时间部分的值 - 列表分区:每个值只能归属一个分区,重复值会报错,缺失值会导致插入失败
查询条件必须能被优化器静态推导出分区范围
剪枝发生在优化阶段,依赖常量表达式或简单参数。以下情况易失效:
- 使用函数包裹分区键:
WHERE YEAR(order_date) = 2024→ 无法剪枝(除非 MySQL 8.0+ 启用函数索引且分区支持) - 使用变量或子查询:
WHERE dt = @last_day或WHERE dt = (SELECT MAX(dt) FROM meta)→ 多数版本不剪枝 - 使用非确定性函数:
WHERE dt = CURDATE()→ 通常不剪枝(MySQL 8.0.30+ 对部分函数有改进,但仍需验证) - 正确写法:
WHERE dt >= '2024-01-01' AND dt → 可精准定位单一分区
用 EXPLAIN PARTITIONS 验证实际剪枝效果
执行 EXPLAIN PARTITIONS SELECT ...,观察 partitions 列是否只列出目标分区。常见误判信号:
-
partitions: NULL→ 未启用分区剪枝(可能是语法错误、引擎不支持或条件不可推导) -
partitions: p202401,p202402,p202403→ 剪枝范围过大,需检查条件松散度 - 即使
type=range,若partitions显示全分区,说明剪枝未生效,索引扫描仍跨多个分区文件
注意分区表达式与查询谓词的逻辑等价性
MySQL 不自动重写表达式。例如分区定义为 PARTITION BY RANGE (TO_DAYS(dt)),则查询必须用 TO_DAYS() 才能剪枝:
- ✅
WHERE TO_DAYS(dt) BETWEEN TO_DAYS('2024-01-01') AND TO_DAYS('2024-01-31') - ❌
WHERE dt BETWEEN '2024-01-01' AND '2024-01-31'→ 即使语义相同,MySQL 通常不推导 - 建议:优先用列本身分区(如
RANGE COLUMNS(dt)),避免函数分区,降低使用门槛
不复杂但容易忽略:每次调整分区策略或上线新查询,都应跑一遍 EXPLAIN PARTITIONS 确认剪枝行为符合预期。










