TRUNCATE比DELETE快,是因为TRUNCATE是DDL操作,直接释放数据段、重置FSEG_HEADER并截断.ibd文件,不扫描聚簇索引、不写undo log、不逐行加锁;而DELETE是DML操作,必须逐行遍历、加锁、写日志、生成binlog事件。

TRUNCATE 比 DELETE 快,不是因为“优化得好”,而是根本没走同一条路——一个是直接拆墙清场,一个是挨个搜身再登记放行。
TRUNCATE 是 DDL,不走 InnoDB 行级引擎
TRUNCATE 不扫描聚簇索引,不读取任何数据页,也不访问一行记录。它直接释放表对应的数据段(segment),重置 FSEG_HEADER,并把 .ibd 文件截断回初始大小(innodb_file_per_table=ON 时可见)。整个过程绕过事务系统、MVCC 和行锁机制。
- 没有
undo log写入,不可回滚 - redo log 只记元数据变更(如 segment 重置),不是逐行修改
- binlog 仅写一条
TRUNCATE TABLE tDDL 事件,而非百万条 row event - 执行完立刻隐式提交,
BEGIN; TRUNCATE TABLE t; ROLLBACK;中的ROLLBACK对它无效
DELETE 是 DML,必须走完整事务流水线
哪怕没写 WHERE,DELETE FROM t 仍是标准 DML:InnoDB 启动事务、遍历聚簇索引、对每行加 X 锁、打 delete bit、写 undo log、生成 binlog row event —— 百万行 = 百万次锁 + 日志 + 刷盘。
- 锁持有时间随数据量线性增长,千万行可能锁表几十秒
-
SHOW ENGINE INNODB STATUS里能看到大量RECORD LOCKS或LOCK_WAIT - 二级索引也要维护 delete bit,物理 I/O 开销翻倍
-
SELECT DATA_LENGTH, INDEX_LENGTH查到的空间占用不变,只是逻辑删除 - 想真正收缩空间,还得额外执行
OPTIMIZE TABLE或ALTER TABLE ENGINE=InnoDB
权限和外键约束处理方式完全不同
TRUNCATE 需要 DROP 权限,不是 DELETE 权限;遇到外键引用或显式 LOCK TABLES t READ 会直接报错退出,不排队、不等待。
ERROR 1099 (HY000): Table 't' was locked with a READ lock-
Cannot truncate a table referenced in a foreign key constraint→ 必须先SET FOREIGN_KEY_CHECKS = 0 - DELETE 则会检查外键约束、触发级联、执行触发器,全程受事务控制
-
SQL_SAFE_UPDATES=1下无WHERE的DELETE直接报ERROR 1175,TRUNCATE 不受此限制
自增 ID 和空间释放效果差异明显
TRUNCATE 会重置 AUTO_INCREMENT 计数器为初始值(通常是 1);DELETE 不会,后续插入仍按原最大值+1递增。
- TRUNCATE 后
.ibd文件大小回落,真实释放磁盘空间 - DELETE 后表文件体积基本不变,空间可被新数据复用,但不会返还给操作系统
- 分区表上
TRUNCATE PARTITION是安全高效的替代方案,而DELETE无法按分区清理
真正容易被忽略的是:TRUNCATE 的“快”,建立在它完全跳过事务锁管理、日志生成和行级处理之上——不是它做得更聪明,而是它压根不参与那套机制。


















