分区表需配合查询逻辑、索引与运维:仅当WHERE含分区键时才生效;RANGE分区适配时间序列,须用可下推函数并控制分区粒度;各子表仍需独立建索引;DROP PARTITION归档高效但需ANALYZE更新统计。

单表数据破千万后性能明显下滑,分区表不是“一键加速”开关,而是需要配合查询逻辑、索引设计和运维节奏的系统性手段。它真正起效的前提是:查询条件中必须带上分区键,否则仍会扫描全部分区,甚至比不分区更慢。
分区键选对,才是有效前提
分区表只在WHERE条件命中分区键时才能自动裁剪分区。比如按create_time做RANGE分区,那么以下查询才高效:
-
WHERE create_time BETWEEN '2026-01-01' AND '2026-03-31'→ 只扫Q1三个分区 -
WHERE user_id = 12345→ 所有分区全扫,毫无优势
注意:分区键必须包含在主键或唯一键中。常见做法是把(user_id, create_time)设为主键,再按create_time分区,兼顾业务查询与约束要求。
RANGE分区最适时间序列场景
订单、日志、行为记录等天然按时间递增的表,用RANGE分区最稳妥:
- 用
TO_DAYS(create_time)而非YEAR(create_time)——函数必须支持索引下推,否则分区失效 - 每个分区覆盖1–3个月数据(如
p202601、p202604),避免按天分区导致超8192个分区报错 - 不用HASH/KEY分区——它们打散时间顺序,让范围查询无法裁剪,且无法用
DROP PARTITION快速归档
分区不等于免索引,子表仍需独立优化
每个分区本质是独立物理子表(如t_order#P#p202603),若单个分区仍有百万级数据,没索引照样慢:
- 高频过滤字段如
status、business_type,必须在每个子表上有对应索引 - 联合索引顺序要贴合实际查询,例如常查
WHERE create_time > ? AND status = ?,索引应为(create_time, status) - 务必用
EXPLAIN PARTITIONS验证:看partitions列是否只列出目标分区,key列是否命中索引
定期归档,释放空间与维护成本
分区带来真正的运维红利,在于旧数据清理快且低影响:
-
ALTER TABLE t_order DROP PARTITION p202501比DELETE FROM ... WHERE create_time 快数倍,不锁全表、不产生大量undo log - 归档后记得更新
information_schema.PARTITIONS统计(需ANALYZE TABLE),避免执行计划误判 - 备份策略需调整:mysqldump默认导出整张逻辑表;物理备份要单独处理每个
.ibd文件



















