分区表核心目的是解决大表维护难题而非提升单条查询性能,适用于日志、订单等按时间递增且数据量持续增长的场景。

分区表的核心目的和适用场景
分区表不是为了提升单条查询性能,而是为了解决大表的维护难题。比如删除历史数据、加快特定范围扫描、减少锁竞争。常见于日志表、订单表、监控数据表等按时间递增且数据量持续增长的场景。
MySQL 支持的分区类型及选择要点
MySQL 5.7+ 主要支持 RANGE、LIST、HASH、KEY 四种分区方式:
-
RANGE 分区:按连续区间划分,最常用在按时间(如
TO_DAYS(create_time)或YEAR(create_time))分月/分年;注意必须是有序、非空、不重叠的表达式。 - LIST 分区:适用于离散值集合,比如按省份编码、业务线编号;需显式列出每个分区包含的值,新增值前要提前添加分区,否则插入失败。
- HASH / KEY 分区:用于均衡分布,HASH 基于用户表达式,KEY 基于列(支持非整型);适合按 ID 均匀打散,但无法做范围查询裁剪,且不能直接删除某一批数据。
分区裁剪(Partition Pruning)是怎么工作的
这是分区表发挥价值的关键机制——优化器根据 WHERE 条件自动识别只访问部分分区,跳过无关分区。但前提是条件中使用的列必须是分区键或其确定性表达式:
- 写
WHERE create_time >= '2024-01-01'可以裁剪,但WHERE DATE(create_time) = '2024-01-01'通常无法裁剪(函数导致索引失效,也影响分区识别)。 - 联合分区(如 RANGE + HASH)下,只有第一级分区键参与裁剪;第二级仅用于子分区内部均匀分布。
- 用
EXPLAIN PARTITIONS查看实际访问了哪些分区,验证是否生效。
分区表的限制与避坑提醒
很多问题在上线后才暴露,面试常考实际落地难点:
- 主键/唯一索引必须包含分区键(否则建表报错),这意味着不能对非分区字段单独建唯一约束。
- 不能跨分区 UPDATE 或 DELETE 涉及多个分区的行(除非用 REPLACE 或先删后插),批量清理历史数据建议用
DROP PARTITION,比DELETE快得多且不锁全表。 - 分区数不宜过多(官方建议 ≤ 100),否则打开表、DDL、统计信息收集开销明显上升;也不宜过少,失去分区意义。
- 分区表不等于分库分表,它仍是单机逻辑,无法解决连接数、IO、CPU 瓶颈;高并发写入仍可能成为热点。
如何判断一张表是否适合分区
别一上来就分,先看真实瓶颈:
- 数据量超过 2000 万行且有明显冷热分离(如只查近 3 个月)?
- 定期归档/删除旧数据,当前用
DELETE导致慢查询或长事务? - 单表备份恢复耗时太久,想按分区并行导出?
- 现有索引已优化到极致,但范围查询仍扫大量数据?
如果以上都不满足,分区反而增加复杂度,得不偿失。










