写点什么

为什么 MySQL 数据删除了一半,表文件体积却没变小?

作者:程序员拾山
  • 2023-01-18
    河南
  • 本文字数:1016 字

    阅读完需:约 3 分钟

1,前言


随着表记录的增加,表体积也会越发变大,为了性能考虑,我们可能会尝试通过 delete 命令,删除部分无用的数据,以期达到减小表体积的效果。不过令人失望的是,即使我们把表中的数据全部删除,表的体积也不会有丝毫的减少。


今天我们来聊聊,缩小表体积的正确姿势。

2,Mysql 是如何删除数据的


我们知道,Mysql 中的数据是以 B+树的形式存放的,当我们删除一条数据时,Mysql 的 innodb 引擎找到这条记录后,只会将这条记录所在的位置标记为删除,而不会真的删除磁盘上的文件。当有新的记录插入时,可能会复用这个位置。


另外,innodb 的数据是按数据页的形式存放的,如果整个页上的数据都被删除了,那这个页就会被标记为可复用了。


所以,即使我们使用 delete 命令删除整个表的记录,也仅仅是所有的数据页被标记为可复用,但是磁盘上的文件,并不会变小。


换句话说,通过 delete 命令是无法回收表空间的。


进一步的,当我们多次使用 delete 命令删除数据后,大量的数据页上会出现很多可以复用而没有被使用的空洞。


当然,除了删除数据会造成空洞,插入、更新数据也会。


总得来说,经过大量增删改的表,基本都会存在很多的数据空洞。如果我们想办法减少这些空洞,自然可以节省大量的表空间。

3,重建表


重建表的逻辑也很简单:新建一个和原表结构一样的表,将原表中的数据,按照主键递增的方式, 把数据一行一行地从原表读出,然后写入新表。


在新表中,主键索引更加紧凑,空间利用率更高,体积自然也更小。


重建表的命令也很简单:


alter table t engine=InnoDB;
复制代码


需要注意的是,Mysql 5.5 版本之前,这个 DDL 命令不是 online 的,在执行此命令时,务必要选择业务低峰期。


从 5.6 版本开始,此命令已被优化为 online DDL。


online DDL 的流程是这样的:


1,扫描原表中的所有数据,生成一颗新的 B+树,将其存入一个临时文件。


2,存入临时文件的过程中,如果有对原表的增删改操作,将这些操作存入一个日志文件。


3,临时文件生成完以后,将日志中的操作重放到临时文件中,这样就得到了一个与原表一样的数据文件。


4,用临时文件替换原表的数据。


由于日志文件的存在,在重建表的过程中,原表仍然是可以操作的,所以可以称之为 online DDL。

4,总结


如果我们要对一个表缩容,仅仅通过 delete 命令删除数据是不行的,需要使用 alter table 命令进行表重建。alter table 在 5.6 之后是 online DDL,但是会消耗大量的 IO 及 CPU,所以建议在业务低峰期使用此命令。5.5 之前的版本,建议业务停止后再进行操作。


写文不易,朋友们点赞关注支持一下吧。

发布于: 刚刚阅读数: 3
用户头像

JAVA技术分享,全网同名 2019-06-19 加入

学习如逆水行舟,不进则退

评论

发布
暂无评论
为什么MySQL数据删除了一半,表文件体积却没变小?_MySQL_程序员拾山_InfoQ写作社区