TRUNCATE 比 DELETE 快得多,因其是 DDL 操作,直接重建表结构、清空数据页并重置自增计数器,不写事务日志;而 DELETE 是 DML,逐行记录 undo log 和 binlog,还触发约束与触发器。

Truncate 为什么比 Delete 快得多
因为 TRUNCATE 是 DDL 操作,直接重建表结构(清空数据页、重置自增计数器),不走事务日志逐行记录;而 DELETE 是 DML 操作,每删一行都写入 undo log 和 binlog(若开启),还要触发触发器、检查外键约束——千万级下 DELETE 可能跑几小时甚至锁表失败。
Truncate 能用的前提条件
必须满足全部以下条件,否则会报错或行为异常:
-
TRUNCATE不支持带WHERE条件,只能清空整表 - 不能在有外键引用的子表上执行(MySQL 会直接拒绝,报错
ERROR 1701 (HY000)) - 不能用于临时表(
TEMPORARY TABLE)或分区表的单个分区(要用ALTER TABLE ... TRUNCATE PARTITION) - 执行用户需具备
DROP权限(不是DELETE权限)
替代 Delete 的安全清理方案(当 Truncate 不能用时)
如果表被其他表外键引用,或只需删旧数据(比如保留最近 3 个月),TRUNCATE 就不可用。此时应分批 DELETE + 主键范围控制:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
DELETE FROM orders WHERE id <p>反复执行直到无匹配行。关键点:</p>
- 必须用主键或有索引的字段做范围条件,避免全表扫描
- 每次
LIMIT建议 5k–10k 行,太大易锁表,太小增加 round-trip 开销 - 执行前关掉 autocommit,手动
COMMIT每批,防止事务日志暴涨 - 注意
binlog_format=ROW下,大事务仍可能打爆磁盘,建议搭配--slave-parallel-type=LOGICAL_CLOCK避免从库延迟
Truncate 后的隐性代价别忽略
快是有代价的:TRUNCATE 会重置 AUTO_INCREMENT 计数器为 1(除非表定义了 auto_increment_offset),且无法回滚(即使在事务里执行也会立即提交)。更隐蔽的是:如果表上有 FULLTEXT 索引,TRUNCATE 后首次插入会触发全文索引重建,可能卡住后续写入;另外,某些监控系统依赖表的 DATA_LENGTH 变化来告警,TRUNCATE 后该值归零,可能触发误报。










