# 为什么 MySQL 不建议使用 delete 删除数据? & Truncate 相关命令用法

delete物理删除其实不能释放磁盘空间,而且会产生大量的碎片,导致索引频繁分裂,影响SQL执行计划的稳定性; 同时在碎片回收时,会耗用大量的CPU,磁盘空间,影响表上正常的DML操作。

我们在业务代码中,建议做逻辑标记删除,避免物理删除。

# 页合并 & 页分裂

B+ Trees (opens new window)动态演示。

MySQL物理删除记录时,不会实际删除这条记录,而是将这条记录标记为已删除,并记录数据页的可回收空间阈值。 当数据页的可回收空间阈值等于MERGE_THRESHOLD(默认为页面大小的50%)时,InnoDB开始寻找最近的页面(NEXTPREVIOUS),以查看是否有机会合并这数据页(碎片回收)。

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

# 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 区别

  1. TRUNCATE TABLE在功能上与不带WHERE子句的DELETE语句相同:二者均删除表中的全部行。但TRUNCATE TABLEDELETE速度快,且使用的系统和事务日志资源少。
  2. DELETE语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。
  3. TRUNCATE TABLE删除表中的所有行,但表结构及其列、约束、索引等保持不变,并且能针对具有自动递增值的字段,做计数重置归零重新计算的作用。
  4. 对于由FOREIGN KEY约束引用的表,不能使用TRUNCATE TABLE,而应使用不带WHERE子句的DELETE语句。由于TRUNCATE TABLE不记录在日志中,所以它不能激活触发器。
  5. TRUNCATE TABLE不能用于参与了索引视图的表。
  6. 对用TRUNCATE TABLE删除数据的表上增加数据时,要使用UPDATE STATISTICS来维护索引信息。
  7. 如果有ROLLBACK语句,DELETE操作将被撤销,但TRUNCATE不会撤销。
  8. 执行TRUNCATE TABLE需要DROP权限。

参考文档

Last Updated: 6 months ago