百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

为什么删除记录表文件不会减小?(记录插入与删除在磁盘的变化)

wptr33 2025-05-03 16:58 27 浏览

如果你熟悉 MySQL 缓冲池(不熟悉可以查看 一条 sql 的执行过程详解),可能会觉得是因为删除操作只更新到缓冲池和 redo log,并没有进行 flush 落盘,但如果关闭数据库,触发 flush ,会发现表文件大小还是不会改变,这是为什么?

原因

首先要了解数据的存储方式,存储方式共有两种,是由参数 innodb_file_per_table 来控制的。

off:共享表结构,表示所有的文件数据存储在同一个文件中,这样在删除整张表后空间也不会被回收,只是被位置被标记为可重用,下次创建表可能就在该位置创建。

on:表示每张表的数据各用一个文件来存储,在删除整张表后该文件也会被回收,减小总占用空间。这也是默认的使用方式。如果存储引擎是 InnoDB ,那么数据文件就是.ibd 格式的,如果是 MyISAM,那么文件就是 .MYD 格式的。


虽然执行 drop 删除表时会减小表文件大小,但在删除记录时还是不能减小结构,这个原因与上面的 off 共享表结构很像,因为 数据页是 InnoDB 管理数据的最小的磁盘单位,数据页就相当于上面的 "一张表的数据",因为一张表的数据页都是存在同一个文件中的,所以在执行 delete 删除数据后只会将将改位置标记可重用,并不会回收,而如果删除整个页,那么也只能将该页标记为可重用而不会回收。这种删除了但是没有被回收的位置就称为 "数据空洞"。

页合并与页分裂

页合并:既然产生了数据空洞,那么数据文件将会变得越来越大,这样是很不利的,所以 MySQL 会在数据空洞达到一定比例后出触发 "页合并",触发的页会找最靠近的可以合并的页进行合并来优化空间(只会将数据页使用权腾出来,并不会减小表文件大小),防止后续的数据插入使用更多的数据页造成文件更大。

页分裂:页分裂是在插入操作时操作的记录主键 ID 在原本的记录之间产生的,因为记录存储在数据页中,如果该数据页没有合适的位置来存储这条记录,那么就会将该条记录以及后面的记录另开要一个数据页来存储。

优化:因为页合并和页分裂都需要消耗额外的性能。所以我们在插入数据时应当按主键递增顺序插入(主键可以使用自增ID 或 雪花算法,但如果业务字段有唯一字段且没有其他索引,那么可以使用其作为主键来避免每次查询都需要回表),删除数据时按主键顺序删除。

如何减小表文件

1、自动触发的页合并。

2、手动触发清理大部分的数据空洞(5.6 的 Online DDL 可能会存一些写操作,可能会产生一些数据空洞),具体做法就是执行 "Alter table 表名 engine = InnoDB",因为 Alter 语句是修改表结构,而执行一个空修改操作就可以在不修改结构的情况下将数据空洞清除。具体原理是会先创建一个临时表,将当前表中的所有记录依次添加到临时表中,最后再将临时表替换原表的表。但是重建表并一定就是最紧凑的,因为在重建时每个数据页会留 1/16 用于更新,同时 5.6 后可能还会在向临时表迁移数据时积累一些写操作造成页分裂。而在这过程中不能有其他操作干扰,比如修改数据、读数据,所以在执行此操作时会添加 MDL 写锁,而在执行读写操作时会添加 MDL 读,两者互斥。

作者:萌新J

原文链接:
https://www.cnblogs.com/mengxinJ/p/14184458.html

相关推荐

oracle数据导入导出_oracle数据导入导出工具

关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...

继续学习Python中的while true/break语句

上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个...

python continue和break的区别_python中break语句和continue语句的区别

python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...

简单学Python——关键字6——break和continue

Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...

2-1,0基础学Python之 break退出循环、 continue继续循环 多重循

用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...

Python 中 break 和 continue 傻傻分不清

大家好啊,我是大田。...

python中的流程控制语句:continue、break 和 return使用方法

Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...

L017:continue和break - 教程文案

continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...

作为前端开发者,你都经历过怎样的面试?

已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...

面试被问 const 是否不可变?这样回答才显功底

作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...

2023金九银十必看前端面试题!2w字精品!

导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。...

前端面试总结_前端面试题整理

记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...

由浅入深,66条JavaScript面试知识点(七)

作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录...

2024前端面试真题之—VUE篇_前端面试题vue2020及答案

添加图片注释,不超过140字(可选)...

今年最常见的前端面试题,你会做几道?

在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...