DELETE
作用:从表中删除一行或多行数据(满足 WHERE 条件的行)
日志:记录每一行被删除的操作(在事务日志中),日志量非常大。
触发器:会触发定义在表上的 BEFORE DELETE 和 AFTER DELETE 触发器。
标识列:不会重置表的自增标识列 。下次插入新数据时,标识列的值会接着删除前的最大值继续增长。
空间:不会立即释放数据页占用的磁盘空间给数据库。空间只是被标记为“可重用”后续的 INSERT 或 UPDATE 可以覆盖这些空间。表所占用的总空间大小通常不会立即减小。
锁:根据 WHERE 条件和数据库实现,可能获得行级锁或页级锁,影响并发性能。
用途:当你需要有选择地删除特定行,或者需要在事务中安全地删除数据(以便可以回滚)时使用。
TRUNCATE
作用:一次性删除表中所有数据。它本质上是将表重置为“初始空状态“
日志:通常只记录整个数据页的释放操作,而不是逐行记录删除,日志量非常小。
触发器:不会触发任何 DELETE 触发器。
标识列:会重置表的自增标识列。
空间:立即释放数据占用的磁盘空间(数据页)还给数据库(由数据库管理,可被其他对象重用)。表文件大小通常会显著减小。
锁:通常需要获取表级锁,在整个操作期间独占锁定该表,阻塞其他所有访问。
用途:当你需要快速、高效地清空整个表的所有数据,并且不需要触发 DELETE 触发器希望重置自增列时使用。比 DELETE FROM table name(不加 WHERE)快得多,尤其对大表。
DROP
作用: 完全删除整个表。这包括表的结构(列定义)、所有数据、索引、约束、触发器以及与该表相关的权限设置。简单说,这个表彻底消失了
日志: 记录删除表的操作。
触发器: 不会触发任何触发器。
标识列: 表都不存在了,自然无所谓重置。
空间: 立即释放该表所占用的所有磁盘空间(数据和索引文件)还给操作系统(由文件系统管理)。
锁: 需要表级锁。
核心区别
特性 | DELETE | TRUNCATE | DROP |
---|---|---|---|
类型 | DML (数据操作语言) | DDL (数据定义语言) | DDL (数据定义语言) |
功能 | 删除部分或全部行 | 删除全部行并重置表 | 删除整个表结构+数据 |
事务支持 | ✅ 可回滚 (需显式事务) | ❌ 隐式提交事务 (不可回滚) | ❌ 隐式提交事务 (不可回滚) |
日志记录 | 逐行记录日志 (undo log) | 记录页级释放操作 (redo log) | 记录删除表的元数据操作 |
执行速度 | 慢 (逐行删除) | 快 (直接回收数据页) | 最快 (直接删除文件) |
WHERE条件 | ✅ 支持筛选删除的行 | ❌ 只能删除全部数据 | ❌ 无数据操作 |
自增ID重置 | ❌ 不重置 | ✅ 重置计数器 (MySQL/PostgreSQL等) | 表不存在了 |
触发器触发 | ✅ 触发DELETE触发器 | ❌ 不触发任何触发器 | ❌ 不触发 |
外键约束影响 | 受外键约束限制 (需级联删除) | ⚠️ 可能被外键阻止 (需无引用) | 直接解除关联关系 |
表结构 | 保留 | 保留 | 永久删除 |
资源消耗 | 高 (事务日志、锁) | 低 | 低 |
恢复难度 | 易 (通过事务回滚或binlog) | 难 (需备份恢复) | 极难 (需重建表+恢复数据) |
各数据库差异
行为 | MySQL(InnoDB) | PostgreSQL | SQL Server |
---|---|---|---|
TRUNCATE回滚 | ❌ 不可回滚 | ✅ 可回滚 | ❌ 不可回滚 |
自增重置 | ✅ | ✅ | ✅ |
触发触发器 | ❌ | ❌ | ❌ (默认) |
总结
DELETE
:像用橡皮擦掉本子(表)上的某些字(行)。本子还在,擦掉的字迹理论上还能辨认(可回滚),但位置空出来了可以写新字。擦特定字很费劲(慢)
TRUNCATE
:像把本子(表)上写满字的所有页(数据页)直接撕掉扔掉,换上空白的页。本子还在,页码(自增ID)从头开始。撕得很快(快),但撕掉的就彻底没了(通常不可回滚)
DROP
:像把整个本子(表)扔进碎纸机。本子没了,里面的字也没了,装本子的位置(磁盘空间)也腾出来了。最彻底的操作。
DELETE
是逐行删除的条件DML操作,可回滚但慢;TRUNCATE
是快速清空全表的DDL操作,重置自增ID但不可回滚;DROP
是删除表结构+数据的终极操作。生产环境优先用 DELETE
保证安全,海量数据清理用 TRUNCATE
(确认无阻塞),废弃表结构才用 DROP
(必须备份!)