当我们的数据库占用空间过大时,经常会想到通过删除部分数据来释放空间,但往往操作完成后会发现表文件的大小并没有发生改变,这是为什么呢?
首先,来看一下数据删除的流程,之后再来分析这个问题产生的原因。
一.数据删除流程
我们知道,InnoDB 里的数据都是用 B+ 树的结构组织的,如下图所示:
假设,我们要删掉 R4 这个记录,InnoDB 引擎只会把 R4 这个记录标记为删除。如果之后要再插入一个 ID 在 300 和 600 之间的记录时,可能会复用这个位置,但是,磁盘文件的大小并不会缩小。
而 InnoDB 的数据是按页存储的,对于数据页来说,如果我们删掉了一个数据页上的所有记录,整个数据页就可以被复用了。
此外,如果相邻的两个数据页利用率都很小,系统就会把这两个页上的数据合到其中一个页上,另外一个数据页就被标记为可复用了。
所以我们知道,如果用 delete 命令把整个表的数据都删除,那所有的数据页都会被标记为可复用,但是磁盘上,文件不会变小。这样看来,通过 delete 命令是不能回收表空间的。这些可以复用,而没有被使用的空间,看起来就像是“空洞”。
实际上,不止是删除数据会造成空洞,插入数据也会。
如果数据是按照索引递增顺序插入的,那么索引是紧凑的。但如果数据是随机插入的,就可能造成索引的数据页分裂,如下图所示&#