为什么删除数据不会减小文件大小

186 阅读3分钟

一、为什么删除一个表的数据不会减少文件大小

1.简单的理解一个表结构

MySQL的底层是使用B+树的结构进行数据存储的,而B+树的叶子节点才是真正存储数据的节点。B+树分为以下2种:

  • 主键索引B+树

    叶子节点存放的是真正的数据行

  • 二级索引B+树

    叶子节点存放的是主键索引相关的信息

因此在通过二级索引检索一个数据时,会拿到主键索引信息,然后去主键索引B+树获取数据。通过主键索引获取数据的流程也叫做“回表”。

2.为什么删除数据不会减少文件大小

当删除一个数据时,并不会将叶子节点直接从B+树上移除掉,而是会将这个记录打上一个标记,“可复用”。如果后续有更新操作(包括插入操作),是有可能直接复用这个数据的。因此,数据并没有真正的被移除,所以文件大小并不会变小。

二、正确优化表文件大小的方法

从上面可知,删除数据并不会减小文件体积。那么该如何优化文件体积呢?

1.为什么可以优化文件大小而数据不丢失

我用一个更新操作来举例。假如一个表存在索引A,此时更新表中索引A=100的数据,设置为A=10000。那么存在以下2个步骤。

  • 删除A=100的数据,即将这个节点标记为“可复用”。
  • 查看在A=10000的数据页中,是否存在“可以复用”的数据,不存在则插入,存在则复用。

数据库操作,简单来将就是增删改查,一个更新操作如果变更了索引字段的数据,则可以理解为一个删除和插入,因为B+树是根据索引字段来建立节点的。因此当这种更新操作变多后,B+树中可能存在很多被标记为“可复用”的节点,这些标记节点上的数据会占用磁盘空间的大小,但并不是真正的数据库数据,删除这些数据,并不会产生影响。

不仅仅是更新操作,一个插入操作如果应该插入到数据页A中,但此时A数据页被写满,则需要进行“页分裂”。此时涉及到“页分裂”的2个数据页的空间利用率都会很低,这也会浪费磁盘空间。

2.正确的优化方式

通俗来将,就是“重建表”。因为重建表时,所有的索引B+树都会重建,此时数据库中的数据都是全新的,不会存在“可复用”的数据,并且也没有“页分裂”导致的数据页空间利用率低的情况,即数据是紧凑的。当然重建主键索引也是一个道理,因为二级索引的叶子节点是包含主键索引的信息的,一旦主键索引变更,所有的B+树也得重建。