• MySQL 45 讲 | 13 为什么表数据删掉一半,表文件大小不变?


    13 | 为什么表数据删掉一半,表文件大小不变?

    数据库中收缩表空间的方法,重建表的方法

    参数innodb_file_per_table

    表数据可以存在共享表空间里,也可以是单独的文件。由参数 innodb_file_per_table控制:

    1. 这个参数设置为OFF表示的是,表的数据放在系统共享表空间,也就是跟数据字典放在一 起

    2. 这个参数设置为ON表示的是,每个InnoDB表数据存储在一个以 .ibd为后缀的文件中。

      从MySQL 5.6.6版本开始,它的默认值就是ON了。

    ​ 建议将这个值设置为ON。因为,一个表单独存储为一个文件更容易管理,而且在不需要这个表的时候,通过drop table命令,系统就会直接删除这个文件。而如果是放在共享表空间中,即使表删掉了,空间也是不会回收的

    数据删除流程

    ​ InnoDB的索引结构为B+树。假设,要删掉R4这个记录,InnoDB引擎只会把R4这个记录标记为删除。如果之后要再插入 一个ID在R4前后记录之间的记录时,可能会复用这个位置。但是,磁盘文件的大小并不会缩小

    • InnoDB的数据是按页存储的,如果删掉了一个数据页上的所有记录整个数据页就可以被复用了。

    数据页的复用跟记录的复用是不同的:

    • 记录的复用,只限于符合范围条件的数据 。
    • 当整个页从B+树里面摘掉以后,可以复用到任何位置
    • 如果相邻的两个数据页利用率都很小,系统就会把这两个页上的数据合到其中一个页上另外一 个数据页就被标记为可复用

    delete命令把整个表的数据删除,所有的数据页都会被标记为可复用。但是磁盘上,文件不会变小 。 也就是说,通过delete命令是不能回收表空间的 。

    • 删除插入更新数据会造成“空洞”( 可以复用,而没有被使用的空间 )。

    • 如果数据是按照索引递增顺序插入的,那么索引是紧凑的。但如果数据是随机插入的,就可能造 成索引的数据页分裂

    重建表

    使用alter table A engine=InnoDB命令来重建表

    ​ 经过大量增删改的表,都是可能是存在空洞的。所以,如果能够把这些空洞去掉,就能达到收缩表空间的目的。 而重建表,就可以达到这样的目的。

    ​ 新建一个与表A结构相同的表B,然后按照主键ID递增的顺序,把数据一行一行地从表A 里读出来再插入到表B中。

    ​ 由于表B是新建的表,所以表A主键索引上的空洞,在表B中就都不存在了。显然地,表B的主键 索引更紧凑,数据页的利用率也更高。如果我们把表B作为临时表,数据从表A导入表B的操作完 成后,用表B替换A,从效果上看,就起到了收缩表A空间的作用。

    • 使用alter table A engine=InnoDB命令来重建表,花时间最多的步骤是往临时表插入数据的过程 。 在MySQL 5.5版本之前执行命令(改锁表DDL, 表A中不能有更新),MySQL会自动完成转存数据、交换表名、删除旧表的操作。

    • 在MySQL 5.6版本开始引入的Online DDL,对这个操作流程做了优化。

      引入了Online DDL之后,重建表的流程 :

      1. 建立一个临时文件,扫描表A主键的所有数据页;
      2. 用数据页中表A的记录生成B+树,存储到临时文件中
      3. 生成临时文件的过程中,将所有对A的操作记录在一个日志文件(row log)中
      4. 临时文件生成后,将日志文件中的操作应用到临时文件,得到一个逻辑数据上与表A相同的 数据文件;
      5. 临时文件替换表A的数据文件
    • 两者不同之处在于,由于日志文件记录重放操作这个功能,在重建表的过程中,允许对表A做增删改操作。这也就是Online DDL名字的来源。

    • 这些重建方法都会扫描原表数据构建临时文件。对于很大的表来说,这个操作是很消耗IO和CPU资源的

    Online 和 inplace

    • 重建表的这个语句alter table t engine=InnoDB,其实隐含的意思是: alter table t engine=innodb,ALGORITHM=inplace; 使用ALGORITHM=copy的时候,表示的是强制拷贝表

    • Online 和 inplace 这两个逻辑之间的关系 :

    1. DDL过程如果是Online的,就一定是inplace的;
    2. 反过来未必,也就是说inplace的DDL,有可能不是Online的。截止到MySQL 8.0,添加全文 索引(FULLTEXTindex)和空间索引(SPATIAL index)就属于这种情况。
    • optimize tableanalyze tablealter table这三种方式重建表的区别:
      • 从MySQL 5.6开始,alter table t engine = InnoDB(也就是recreate)默认的就是的Online DDL流程了;
      • analyze table t 其实不是重建表,只是对表的索引信息做重新统计,没有修改数据,这个过程中加了MDL读锁
      • optimize table t 等于recreate + analyze

    小结

    • 数据库中收缩表空间的方法
    • delete掉表里面不用的数据的话,表文件的大小是不会变
    • 通过alter table命令重建表,才能达到表文件变小的目的
    • 重建表的两种实现方式
      • Online DDL的方式是可以考虑在业务低峰期使用
      • MySQL 5.5及之前的版本,这个命令是会阻塞DML
  • 相关阅读:
    项目管理仅关注交付结果不够,价值实现是未来趋势
    【ROS】Nav2源码之nav2_behavior_tree详解
    CleanMyMac X2024免费版苹果电脑杀毒工具
    IO流(复习)
    [附源码]Python计算机毕业设计Django小型银行管理系统
    HALCON联合C#机械手视觉定位——界面代码
    2.一步一步教你使用pycharm运行起第一个Django项目
    面试经典150题——Day36
    python中json的使用dump,dumps,loads,load简单了解
    在css中设计好看的阴影
  • 原文地址:https://blog.csdn.net/weixin_43806049/article/details/126370324