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

标签: mysql 数据库 | 发表时间:2023-06-07 15:58 | 作者:江南一点雨
出处:https://segmentfault.com/blogs

上篇文章结尾和小伙伴们留了一个小问题,就是关于 optimize table 命令,今天我想花点时间再来和小伙伴们聊一聊这个话题。

1. 删除空洞

1.1 案例展示

首先我们先来看这样一个例子。

我现在有一个名为 sakila 的数据库,该库中有一个 film 表,这个表中有 1000 条记录,我么先来看下这 1000 条记录占用了多少存储空间:

小伙伴们可以看到,这个文件大小是 360448 个字节。

我们现在执行 delete 命令将这个表清空:

  delete from film;

然后再来查看这个文件的大小:

小伙伴们看到,这个表中的数据没有减少,甚至还增加了!这是咋回事?

1.2 分析

以下所说的删除皆指通过 delete 命令删除,不包括通过 truncate/drop 删除。

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

经过前面文章的介绍,小伙伴们应该已经清楚,MySQL 表中的数据最终是以 B+Tree 的形式保存在磁盘中的,当你要删除一条记录的时候,那么对应的叶子上的数据就会被标记为已删除,类似下面这样:

当 ID 为 6 的记录被删除掉之后,这块空间并不会立马被释放出来,MySQL 只是在这个位置做一个删除标记,将来要是还有一个 ID 为 6 的数据被插入进来,就会插入到这里。

因此我们看到,一张表在经过 N 多次删除之后,就会出现大量这种情况,这种就称之为删除空洞。

2. 插入空洞

前面所说的删除会造成空洞,其实插入也会造成空洞。

松哥在之前的文章中和小伙伴们分享过,InnoDB 引擎的表中不建议使用随机字符串作为 ID,因为随机字符串插入会造成页分裂。页分裂之后,在分裂之前的叶子中,也有可能会空出来新的空间,造成空洞。

例如下面这个例子:

在上图这个 B+Tree 中,继续插入 5,就会造成页分裂,页分裂之后,2 所在的数据页(InnoDB 操作磁盘的最小单位是数据页)就会有空余,这也是空洞的一种。

当然更新索引上的值也会造成空洞,因为更新相当于插入+删除。

3. optimize table

想要解决这个问题,我们可以使用 optimize table 命令来实现。该命令可以用来重新整理表空间,并优化文件碎片。接下来我们针对前面 1.1 小节中的案例,来试试 optimize table 命令是否有效:

这上面有一句提示,说 Table does not support optimize, doing recreate + analyze instead,看这个意思,似乎是说当前这个 InndoDB 引擎的表不支持 optimize 操作,不过我们不用管,我们现在去查看表文件大小:

可以看到,表文件数据其实已经减少了。

那么这句提示是咋回事呢?

我们以 MySQL 官方文档介绍为准来看下:

从这段话中可以看到,在 InnoDB 中使用 optimize 命令,相关的操作最终会被映射为 alter table ...,这个操作松哥在 上篇文章中和小伙伴们介绍过了,这也可以实现索引的重整并且释放掉未使用的空间,所以,网上有人说 optimize table 命令不适用于 InnoDB 引擎的表这个说法是不正确的。

同时,官方文档中这段介绍还提到了 optimize 操作是 online DDL 的。online DDL 意味着在执行 optimize 重整表的时候,并不会阻塞正在进行的 CURD 操作。具体流程如下:

  1. 首先建立一个临时文件,这个临时文件用来扫描表原始表主键的所有数据页。
  2. 根据第一步获取到的表记录生成一个 B+Tree,将这个生成的 B+Tree 存储到临时文件中。
  3. 由于第二步会比较耗时,在第二步执行过程中,如果有针对原始表的 CRUD 操作,则先将操作记录到一个日志文件中,等到第二步的临时文件生成后,在把日志文件应用到临时文件中,就可以获取到一个最新的数据表了。

好啦,这就是关于 optimize table 的操作细节,小伙伴们 GET 到了吧~

相关 [delete 磁盘空间 变化] 推荐:

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

- - SegmentFault 最新的文章
上篇文章结尾和小伙伴们留了一个小问题,就是关于 optimize table 命令,今天我想花点时间再来和小伙伴们聊一聊这个话题. 我现在有一个名为 sakila 的数据库,该库中有一个 film 表,这个表中有 1000 条记录,我么先来看下这 1000 条记录占用了多少存储空间:. 小伙伴们可以看到,这个文件大小是 360448 个字节.

几招省磁盘空间的方法

- - OurMySQL
   我们在工作中时常会遇到一些客户的TPS\QPS都不太高,但磁盘占用非常大,一旦单实例空间太大,像内存、网络、CPU以及备份都将增加相应的开销. 可能仅仅是由于空间不满足使得我们不得不进行扩容,下面的方法提供给大家参考.    1) 字符集是否遵循了最小化原则?(能用latin的就不用gbk.    2) 索引上是否有滥用.

磁盘空间不足的临时解决方案

- - OurMySQL
    一、通过软连接的方式迁移部分表空间到其他硬盘.    优点:对数据没有任何影响,反而可以适当增加IO能力,使用多个磁盘的IOPS.    1、关掉mysql实例.    6、启动数据库,检查是否异常.    7、删掉 remove的文件..     二、通过blackhole引擎,清理掉一些不重要,但是占用空间较大的表.

Delete删除表数据时对性能的影响分析

- - CSDN博客数据库推荐文章
上一篇博客中提到,当我们用delete删除数据时,因为无法降低高水位,对表做全表扫描时会带来数据库性能问题,而truncate可以大大改善这一状况,下面来看测试. --创建表之前先记录下剩余表空间大小. ZLM                                     6        128   51380224       6272            6.

为什么MySQL不建议delete删除数据

- - 掘金后端本月最热
有情怀,有干货,微信搜索【. 三太子敖丙】关注这个不一样的程序员. github.com/JavaFamily 已收录,有一线大厂面试完整考点、资料以及我的系列文章. 我负责的有几个系统随着业务量的增长,存储在MySQL中的数据日益剧增,我当时就想现在的业务方不讲武德,搞偷袭,趁我没反应过来把很多表,很快,很快啊都打到了亿级别,我大意了,没有闪,这就导致跟其Join的表的SQL变得很慢,对的应用接口的response time也变长了,影响了用户体验.

Chrome OS 会在磁盘空间不足之时自动删除用户数据

- delphij - 谷奥——探寻谷歌的奥秘
在最新版的Chrome OS Dev分支 (14.0.835.87) 里,文件管理器最底部多出了一行提示,说:. 警告:这些临时文件可能会被自动删除以释放磁盘空间. 如果你的Chromebook磁盘空间不多的时候,你的浏览器数据会被自动删除. 在需要额外空间的时候,超过3个月没登录过的非拥有者帐户的信息都会被删除(包括下载的文件).

SpaceSniffer — 找出侵占你磁盘空间的罪魁祸首 | 小众软件 > 实用工具

- manabomb - 小众软件 - Appinn
SpaceSniffer是一个运行于 Windows 下的磁盘空间占用查看工具. 打开“计算机”,鲁二狗看着那几行红红的硬盘空间条又郁闷了:硬盘又满了,想清理一下还不知道哪个文件占的空间,于是向 root 请教. root 麻利地拿出 SpaceSniffer 给鲁二狗传去,于是各种超大的文件全部浮出水面,而且 SpaceSniffer 支持直接选中之后的 Windows 右键菜单,这样就可以直接删除了(当然,不按住 Shift 的话最后还得清空回收站).

TCP 状态变化

- - 互联网 - ITeye博客
关闭socket分为主动关闭(Active closure)和被动关闭(Passive closure)两种情况. 前者是指有本地主机主动发起的关闭;而后者则是指本地主机检测到远程主机发起关闭之后,作出回应,从而关闭整个连接. 将关闭部分的状态转移摘出来,就得到了下图:. 通过图上,我们来分析,什么情况下,连接处于CLOSE_WAIT状态呢.

Flashcache新版重大变化

- Eric - Erlang非业余研究
原创文章,转载请注明: 转载自Erlang非业余研究. 本文链接地址: Flashcache新版重大变化. facebook释出的flashcache见 https://github.com/facebook/flashcache, 也可以参考我之前写的 ppt 如何使用,或者参考我们的dba写的详细使用和配置,见 这里, 这里, 这里.