DROP PARTITION比DELETE快得多,因其是DDL操作,不走事务日志、不生成undo/redo、不触发索引维护和触发器;而DELETE需逐行处理,开销巨大。

分区表本身不自动归档,但能极大简化归档操作——关键在于用 PARTITION BY RANGE 搭配时间字段,让 DROP PARTITION 成为毫秒级归档动作;前提是建表时就满足硬约束,否则后续所有优化都白搭。
为什么 DROP PARTITION 比 DELETE 快得多
因为它是 DDL 操作,不走事务日志、不生成 undo/redo、不触发索引维护和触发器。而 DELETE FROM ... WHERE create_time 在千万级表上会:锁大量页、撑爆 buffer pool、产生巨量 binlog、拖慢主从同步。
-
DROP PARTITION p_2024_q1执行后,该分区对应的所有数据物理删除,InnoDB 不做行级清理 - 但注意:磁盘空间不会立刻释放,
ibd文件大小不变,需后续OPTIMIZE TABLE或重建表才能回收 - 必须确保该分区已无任何业务查询依赖,否则删完就查不到——不是性能问题,是逻辑错误
建表时主键必须包含分区键,否则直接失败
MySQL 强制要求:如果表有主键或唯一索引,分区键必须是其一部分。这不是建议,是语法级报错条件。
- 错误写法:
PRIMARY KEY (id)+PARTITION BY RANGE COLUMNS(create_time)→ 报错ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function - 正确写法:
PRIMARY KEY (id, create_time)或PRIMARY KEY (create_time, id) - 若原表已有自增主键
id,得先ALTER TABLE t DROP PRIMARY KEY,再ADD PRIMARY KEY(id, create_time) - 别图省事只加
UNIQUE KEY (create_time):它无法替代主键约束,仍会报错
分区裁剪(pruning)失效的三个典型场景
即使建表合规,查询仍可能全表扫描——根本原因是优化器无法推导出目标分区。验证是否生效,唯一可靠方式是:EXPLAIN PARTITIONS SELECT * FROM t WHERE create_time >= '2025-01-01',看 partitions 列是否只列出几个分区名。
-
WHERE YEAR(create_time) = 2025:函数包裹分区键,裁剪失效,partitions: NULL -
WHERE create_time BETWEEN '2025-01-01' AND '2025-06-30':正常裁剪,但必须确保边界值与分区定义对齐(如分区是按月,LESS THAN ('2025-07-01')) -
WHERE user_id = 123:分区键未出现在 WHERE 条件中,所有分区都要扫,还多一层元数据开销
TO_DAYS() 分区边界怎么写才不翻车
用 TO_DAYS() 是为了把日期转成单调递增整数,避免跨时区/夏令时问题。但它对输入格式极其敏感,错一个字符就建表失败。
- 错误:
LESS THAN (TO_DAYS('2025-01'))→ 报错,'2025-01'不是合法 DATE 字面量 - 正确:
LESS THAN (TO_DAYS('2025-02-01'))表示“2025 年 1 月及之前”,不是'2025-01-31' - 必须保证初始分区覆盖未来至少 3 个月,否则插入超前数据会报
ERROR 1526 (HY000): Table has no partition for value - 永远不要用
UNIX_TIMESTAMP()做分区表达式:夏令时切换时结果跳变,导致分区错乱
最容易被忽略的是:分区表的物理路径管理依赖 innodb_file_per_table=ON,否则所有分区共用一个 ibd 文件,DROP PARTITION 就失去意义;另外,EXPLAIN PARTITIONS 必须在真实查询条件下跑,不能只看建表语句是否“看起来合理”。


















