# 为什么 MySQL 不建议使用 delete 删除数据? & Truncate 相关命令用法
delete
物理删除其实不能释放磁盘空间,而且会产生大量的碎片,导致索引频繁分裂,影响SQL
执行计划的稳定性;
同时在碎片回收时,会耗用大量的CPU
,磁盘空间,影响表上正常的DML
操作。
我们在业务代码中,建议做逻辑标记删除,避免物理删除。
# 页合并 & 页分裂
B+ Trees (opens new window)动态演示。
MySQL
物理删除记录时,不会实际删除这条记录,而是将这条记录标记为已删除,并记录数据页的可回收空间阈值。
当数据页的可回收空间阈值等于MERGE_THRESHOLD
(默认为页面大小的50%
)时,InnoDB
开始寻找最近的页面(NEXT
和PREVIOUS
),以查看是否有机会合并这数据页(碎片回收)。
在B+Tree
中,所有的叶子节点都是按键值的大小顺序存放在同一层的叶子节点上,由各叶子节点指针双向链表关联起来。
如果你自定义了主键索引,且这个主键索引不是自增的,那么随着数据的写入,导致要写入数据页已满且后面一个数据页中数据页也满,无法正常写入,触发页分裂的逻辑。
页分裂的B+Tree
实际上在物理上可能是乱序的,并且大多数情况下是不同程度的物理上乱序。这就是为啥,我们要求使用自增长ID
的原因。
# DROP TABLE (DDL)
使用DROP TABLE
命令可以快速删除MySQL中的数据表。该命令的语法如下:
DROP TABLE table_name1, table_name2, ...;
1
# TRUNCATE TABLE (DDL)
TRUNCATE TABLE
命令用于清空MySQL
中的数据表中的数据,
TRUNCATE TABLE table_name;
TRUNCATE table_name;
1
2
2
# DELETE FROM (DML)
DELETE FROM命令用于删除表中的数据。该命令仅删除表中的记录,如果您需要删除特定的行,可以使用WHERE子句。该命令的语法如下:
DELETE FROM table_name [WHERE condition];
1
# DROP DATABASE (DDL)
可以使用DROP DATABASE
删除整个数据库。
DROP DATABASE database_name;
1
# TRUNCATE 与 DELETE FROM 区别
TRUNCATE TABLE
在功能上与不带WHERE
子句的DELETE
语句相同:二者均删除表中的全部行。但TRUNCATE TABLE
比DELETE
速度快,且使用的系统和事务日志资源少。DELETE
语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE
通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。TRUNCATE TABLE
删除表中的所有行,但表结构及其列、约束、索引等保持不变,并且能针对具有自动递增值的字段,做计数重置归零重新计算的作用。- 对于由
FOREIGN KEY
约束引用的表,不能使用TRUNCATE TABLE
,而应使用不带WHERE
子句的DELETE
语句。由于TRUNCATE TABLE
不记录在日志中,所以它不能激活触发器。 TRUNCATE TABLE
不能用于参与了索引视图的表。- 对用
TRUNCATE TABLE
删除数据的表上增加数据时,要使用UPDATE STATISTICS
来维护索引信息。 - 如果有
ROLLBACK
语句,DELETE
操作将被撤销,但TRUNCATE
不会撤销。 - 执行
TRUNCATE TABLE
需要DROP
权限。
参考文档