Mysql之delete

Posted by Wh0ami-hy on July 20, 2024

1. delete和truncate

delete和truncate都是用于删除数据库表中数据的SQL语句,但是它们有以下几个区别:

1 . 对表结构的影响:

  • DELETE 语句删除表中的数据行,不会删除表的结构(表名、列等)。
  • TRUNCATE 语句删除表中的所有数据行,不会删除表的结构(表名、列等),并重置表的自增长列的计数器。同时也会释放表占用的存储空间。

2 . 执行速度:

  • TRUNCATE 语句通常比 DELETE 语句执行得更快,因为它只需要重置表的数据页,而不需要遍历整个表来删除每一行数据。

3 . 事务日志记录:

  • DELETE 语句会将每个被删除的行记录到事务日志中,因此可以进行回滚操作。
  • TRUNCATE 语句会直接从磁盘中删除数据页,不会记录到事务日志中,因此无法进行回滚。

4 . WHERE 子句:

  • DELETE 语句可以使用 WHERE 子句来有选择地删除满足条件的行。
  • TRUNCATE 语句无法使用 WHERE 子句,它会删除整个表的所有数据行。

总的来说,如果需要删除表中的全部数据,并且不需要保留删除记录,那么使用 TRUNCATE 语句更加高效。如果需要有选择地删除部分数据行,并且需要保留删除记录以便于回滚,那么使用 DELETE 语句更合适。

TRUNCATE TABLE table_name;

2. 自增列的问题

使用 DELETE 语句删除记录后,自增列的值不会自动重置。这是 MySQL 设计的一部分,旨在确保新的记录不会重复使用已删除记录的自增值。如果确实需要重置自增列的值,可以使用 ALTER TABLE 语句,但应谨慎操作,以避免数据完整性问题

-- 重置自增列的起始值,
ALTER TABLE employees AUTO_INCREMENT = 2;
-- 下一条插入的新记录的 `id` 将会是 `2`,但如果已经存在 `id` 为 `2` 的记录,会导致插入失败

2.1. InnoDB 自增列

在 InnoDB 存储引擎中,自增列的当前计数器值是存储在内存中的。这意味着:

  • 在数据库运行期间,自增列的值会随着每次插入操作而递增。
  • 如果数据库服务重启,自增列的计数器会重新初始化。

重启后的行为

  • MySQL 5.6 及更早版本:自增列的计数器会从表中最大的现有自增列值加一开始。
  • MySQL 5.7 及更高版本:自增列计数器的行为进行了优化,通常会继续从上次插入的最大值加一开始。

2.2. MyISAM 自增列

在 MyISAM 存储引擎中,自增列的当前计数器值是存储在磁盘上的。这意味着:

  • 自增列的值会随着每次插入操作而递增。
  • 即使数据库服务重启,自增列的计数器值也不会丢失。

重启后的行为

  • MyISAM:自增列的值会继续从上一个自增值加一开始,无论数据库是否重启

3. delete 清空表之后,磁盘空间未发生变化

3.1. 原理

MySQL 中的delete数据删除操作有点像我们平日里做业务开发时用的逻辑删除,当你想要删除掉一行数据的时候,这行数据其实并没有被真正的删除掉,只是暂时给标记为删除了而已

一张表在经过 N 多次delete删除之后,就会出现大量这种情况,这种就称之为删除空洞

3.2. optimize table

optimize table table_name

该命令可以用来重新整理表空间,并优化文件碎片

optimize 操作是 online DDL 的。online DDL 意味着在执行 optimize 重整表的时候,并不会阻塞正在进行的 CURD 操作。具体流程如下:

1 . 首先建立一个临时文件,这个临时文件用来扫描表原始表主键的所有数据页。

2 . 根据第一步获取到的表记录生成一个 B+Tree,将这个生成的 B+Tree 存储到临时文件中。

3 . 由于第二步会比较耗时,在第二步执行过程中,如果有针对原始表的 CRUD 操作,则先将操作记录到一个日志文件中,等到第二步的临时文件生成后,在把日志文件应用到临时文件中,就可以获取到一个最新的数据表了。


本站总访问量