DROP PARTITION 比 DELETE 快因属元数据操作,不扫描行、不写日志、不更新索引;而 DELETE 生成大量 undo/redo、锁表久、易致缓冲池雪崩。

为什么 DROP PARTITION 比 DELETE 快得多
因为 DROP PARTITION 是元数据操作,不逐行扫描、不走事务日志、不触发索引更新;而 DELETE 会生成大量 undo/redo 日志,锁表时间长,还可能让缓冲池雪崩。尤其在几十亿行的 orders 表上,DELETE FROM orders WHERE dt = '2023-01-01' 可能跑几小时甚至失败,但删一个分区秒级完成。
按天分区必须用 RANGE COLUMNS(dt),别用 DATE 函数
常见错误是写成 PARTITION BY RANGE (TO_DAYS(dt)) 或 PARTITION BY RANGE (YEAR(dt)*100+MONTH(dt)) —— 这会导致 MySQL 无法做 partition pruning,查询仍要扫全表。正确做法是:
ALTER TABLE logs PARTITION BY RANGE COLUMNS(dt) (
PARTITION p20230101 VALUES LESS THAN ('2023-01-02'),
PARTITION p20230102 VALUES LESS THAN ('2023-01-03'),
PARTITION p20230103 VALUES LESS THAN ('2023-01-04')
);-
dt字段必须是DATE或DATETIME类型,不能是字符串 - 每个分区上限值写成字符串字面量(如
'2023-01-02'),MySQL 才能精确匹配 - 分区名建议带日期,方便脚本识别和清理
自动删旧分区的脚本要避开 LOCK_WAIT 和元数据锁
直接在业务高峰期跑 ALTER TABLE logs DROP PARTITION p20230101 可能被大查询阻塞,甚至卡住 DDL 线程。安全做法:
- 用
SELECT * FROM information_schema.INNODB_TRX先查有没有长事务,避免 DDL 等锁 - 加
WAIT 3超时:ALTER TABLE logs WAIT 3 DROP PARTITION p20230101 - 删除前先
FLUSH TABLE logs,减少表缓存干扰 - 脚本里用
mysql -e "SHOW CREATE TABLE logs"动态获取最老分区名,别硬编码
分区后 COUNT(*) 和 MAX(dt) 查询反而变慢?
这是典型误区:分区不是万能加速器。如果没走分区裁剪,比如 SELECT COUNT(*) FROM logs WHERE id > 1000(id 非分区键),MySQL 仍要遍历所有分区。更麻烦的是:
-
COUNT(*)在 InnoDB 分区表上无法用采样估算,必须真实统计每一分区行数再累加 -
MAX(dt)如果dt是分区键,会快;但MAX(id)就得扫全部分区 - 分区数太多(比如超 512)会让
information_schema查询变慢,影响监控脚本
分区本质是管理手段,不是性能银弹。删数据爽,查数据未必快——这点容易被忽略。


















