MySQL之表碎片化
文章目录
- 1. 前言
- 2. InnoDB表碎片
- 3. 清除表碎片
- 3.1 查找碎片化严重的表
- 3.2 清除碎片
- 4. 小结
- 5. 参考
1. 前言
周一在对线上表进行数据清除时,发现一个问题,我要清除的单表大概有2500w条数据,清除数据大概在1300w条左右,清除之前通过查询语句获取到的表大小约为7000MB。
SELECT table_name as Table, round(((data_length + index_length) / 1024 / 1024), 5) as Size(MB) FROM information_schema.tables WHERE table_schema ='db_name' AND table_name = 'table_name'\G
通过脚本清除之后,再通过查询语句获取表大小,发现表仍然有6000MB的数据剩余。感觉肯定是有对应的一些索引数据没有被删除掉,仍然保存在表中,导致表空间仍然很大。
后面了解到这个是MySQL的数据碎片,加上使用的是MySQL的InnoDB引擎,导致即使我们删除数据,表空间也不会缩小,需要通过一些额外的表优化手段来清除这些数据碎片,因为用的是InnoDB引擎,所以就看了下关于InnoDB引擎表碎片相关的知识。
2. InnoDB表碎片
InnoDB表的数据存储在页(page)中,每个页可以存放多条记录,InnoDB默认使用B+树作为索引结构,表中的数据和辅助索引都是使用B+树结构,每个InnoDB表中都有一个称为聚簇索引的特殊索引,用于存储行数据。通常聚簇索引与主键索引同义。
通过聚簇索引访问行的速度很快,以为索引搜索会直接找到包含行数据的页面,如果表很大,与使用与索引记录不同的页面存储行数据的存储组织相比,聚簇所以架构通常可以节省磁盘I/O操作。
除了聚簇索引之外,还有一个二级索引,我们也叫做辅助索引。在InnoDB中,辅助索引中的每个记录都包含行的主键列以及为二级索引指定的列,InnoDB使用此主键值在聚簇索引中搜索行。如果主键很长,则辅助索引将使用更多的空间,因此使用较短的主键是比较好的。
对于InnoDB而言,随机插入或者删除辅助索引可能会导致索引碎片化,碎片化意味着磁盘上索引页的物理顺序与页面上记录的索引顺序不接近,或者分配给索引的64页块中有许多未使用的页面。
**碎片的一个症状是表占用的空间比它“应该”占用的空间要多,**具体会多多少很难确定。所有InnoDB数据和索引都存储在B树种,它们的填充因子可能从50%到100%不等。碎片的另一个症状是表扫描花费的时间比它“应该”花费的时间要多。
在InnoDB中,删除一些行,InnoDB并不会真正的删除它们,只是会将这些行标记为“已删除”(同时也称为可复用的位置,即后续如果有对应的主键数据插在这段区域,会复用位置),而不是真的从索引中物理删除,因此存储空间也没有真的被释放。
删除数据会导致页中出现空白空间,大量随机的DELETE操作会在数据文件中造成不连续的空白空间,当插入数据的时候,这些可复用的空白空间会被利用起来,但这会造成数据存储位置的不连续,即物理存储顺序与逻辑上的排序顺序不同,于是就产生了表数据碎片。
对表进行大量的UPDATE操作也可能会导致页分裂,频繁地页分裂,页会变得稀疏,并且被不规则的填充,继而产生表碎片,
另外,表的数据存储也可能会碎片化,数据存储的碎片化比索引更加复杂,主要有三种类型的数据碎片:
- 行碎片(Row fragmetation)
- 指数据行被存储在多个地方的片段中,即使查询只从索引中访问一行记录,行碎片也会导致性能下降
- 行间碎片(Intra-row fragmetaion)
- 行间碎片是指逻辑上顺序的页或者行在磁盘上不是顺序存储的,行间碎片对诸如全表扫描和聚簇索引扫描之类的操作有很大的影响,因为这些操作原本能从磁盘顺序存储的数据中获益
- 剩余空间碎片(Free space fragmenation)
- 指数据页中有大量的空余空间,会导致服务器读取大量不需要的数据,从而造成浪费。
对于MyISAM表,上述三类碎片化都有可能发生,但InnoDB不会出现短小的行碎片,InnoDB会移动短小的行并重写到一个片段中。
3. 清除表碎片
删除了数据而空间没有得到释放,于是我们需要采取一些手段来清除删除的数据留下的表碎片,从而释放存储空间,同时提升查询效率。
3.1 查找碎片化严重的表
对于表中是否含有碎片,可以通过下面的命令直接查看表信息。
show table status from db_name like '%table_nam%'\G
mysql> show table status like '%user_tab%'\G
*************************** 1. row ***************************Name: user_tabEngine: InnoDBVersion: 10Row_format: DynamicRows: 4 -- 可以看到有4行数据Avg_row_length: 4096Data_length: 16384
Max_data_length: 0Index_length: 16384Data_free: 0 -- 可释放的空间为0Auto_increment: 5Create_time: 2023-08-12 16:58:07Update_time: 2024-06-23 16:38:08Check_time: NULLCollation: utf8_general_ciChecksum: NULLCreate_options: Comment:
-- 插入一些数据,然后看Data Free,发现有许多可释放的数据
mysql> show table status like 'user_tab'\G
*************************** 1. row ***************************Name: user_tabEngine: InnoDBVersion: 10Row_format: DynamicRows: 351Avg_row_length: 10502Data_length: 3686400
Max_data_length: 0Index_length: 1589248Data_free: 9437184Auto_increment: 41282Create_time: 2023-08-12 16:58:07Update_time: 2024-06-23 17:00:29Check_time: NULLCollation: utf8_general_ciChecksum: NULLCreate_options: Comment:
1 row in set (0.00 sec)
3.2 清除碎片
清理碎片主要有两种方式:
第一种是优化表,即OPTIMIZE TABLE,这种方式会重组表和索引的物理存储,减少对存储空间的使用和提升访问表的I/O效率。OPTIMIZE操作会暂时锁住表,数据量越大,则耗时越长。对每个表所做的确切更改取决于该表使用的存储引擎。
对于InnoDB表,OPTIMIZE TABLE
会映射到ALTER TABLE … FORCE
, 这将重建表以更新索引统计信息并释放聚簇索引中未使用的空间。
对刚刚的user_tab采用OPTIMIZE的命令,可以看到空间被释放了。
mysql> optimize table user_tab\G
*************************** 1. row ***************************Table: duanxi.user_tabOp: optimize
Msg_type: note
Msg_text: Table does not support optimize, doing recreate + analyze instead
-- 实际采用的事recreate + analyze方式
*************************** 2. row ***************************Table: duanxi.user_tabOp: optimize
Msg_type: status
Msg_text: OK
2 rows in set (0.04 sec)mysql> show table status like 'user_tab'\G
*************************** 1. row ***************************Name: user_tabEngine: InnoDBVersion: 10Row_format: DynamicRows: 7Avg_row_length: 2340Data_length: 16384
Max_data_length: 0Index_length: 16384Data_free: 0 -- 优化后Data Free变为0了Auto_increment: 41282Create_time: 2024-06-23 17:02:48Update_time: NULLCheck_time: NULLCollation: utf8_general_ciChecksum: NULLCreate_options: Comment:
1 row in set (0.00 sec)
InnoDB的OPTIMIZE TABLE对常规表和分区表使用在线DDL方式,从而减少并发DML操作的停机时间。由OPTIMIZE TABLE触发的表重建会在原地完成,在操作的准备阶段和提交阶段,只短暂地采用排它表锁,在准备阶段,更新元数据并创建中间表,在提交阶段,提交表元数据更改。
在线DDL(MySQL 8.0+)
在线 DDL 功能支持即时、就地表更改和并发 DML。此功能的优点包括:
- 在繁忙的生产环境中提高响应能力和可用性,因为让表不可用几分钟或几小时是不切实际的。
- 对于就地操作,可以使用
LOCK
子句在 DDL 操作期间调整性能和并发之间的平衡。- 与表复制方法相比,磁盘空间使用量和 I/O 开销更少。
OPTIMIZE TABLE在以下情况下使用表赋值方法重建表
- 当
old_alter_table
系统变量启用时 - 当服务器使用
—skip-new
选项启动时
InnoDB使用页面分配方法存储数据,不会像传统存储引擎(例如MyISAM)那样收到碎片的影响,在考虑是否运行优化时,请考虑你的服务器预计要处理的事务的工作负载。
- 预计会出现一定程度的碎片,InnoDB仅填充93%的页面,以便留出更新空间,而无需拆分页面
- 删除操作可能会留下空隙,导致页面填充不足,这可能会使优化表变得有价值
- 当有足够的空间时,对行的更新通常会重写同一页内的数据,具体取决于数据类型和行格式。
- 高并发工作负载可能会随着时间的推移在索引中留下空白,因为InnoDB通过其MVCC机制保留了同一数据的多个版本。
对于MyISAM,OPTIMIZE TABLE工作原理如下:
- 如果表有删除或拆分行,则修复该表。
- 如果索引页未排序,则对其进行排序。
- 如果表的统计信息不是最新的(并且无法通过对索引进行排序来完成修复),则更新它们。
第二种操作则是使用ALTER TABLE table_name ENGINE= InnoDB;
的方式,此方式看起来没有执行什么操作,实际上重新整理碎片了,当执行这个优化操作时,InnoDB会重建整个表并释放聚簇索引中未使用的空间。
4. 小结
因为删除表数据发现表使用空间未被释放,继而发现有表碎片问题,查找一些资料去了解表碎片的产生以及表碎片的处理,最终让自己学习到了关于InnoDB表碎片相关的知识。
表碎片的产生主要是InnoDB删除非物理删除,而是标记”删除”,且这些被“删除”的空间后续还可复用,进而导致磁盘上索引页的物理顺序与页面上记录的索引顺序不接近,引发表的碎片化。同时表的大量更新、表的数据存储页都会产生不同的表碎片。
表碎片的清除手段:
- OPTIMIZE TABLE table_name;
- ALTER TABLE table_name ENGINE = InnoDB;
需要注意的是,无论我们采用哪种手段清除表碎片,都会有锁表的时间,我们需要根据自己服务器要处理的事务的工作负载分析,研判这种锁表时间对于业务是否接受,如果可以接受则可以对表碎片进行优化,如果不能接受,则无需进行优化,等待后续再进行优化。(思考再三,我选择放弃优化,让碎片继续留在表中)
5. 参考
- Defragmenting a Table
- Overview of fragmented MySQL InnoDB tables
- OPTIMIZE TABLE Statement
相关文章:

MySQL之表碎片化
文章目录 1. 前言2. InnoDB表碎片3. 清除表碎片3.1 查找碎片化严重的表3.2 清除碎片 4. 小结5. 参考 1. 前言 周一在对线上表进行数据清除时,发现一个问题,我要清除的单表大概有2500w条数据,清除数据大概在1300w条左右,清除之前通…...

碳+绿证如何能源匹配?考虑碳交易和绿证交易制度的电力批发市场能源优化程序代码!
前言 近年来,面对日益受到全社会关注的气候变化问题,国外尤其是欧美等发达国家和地区针对电力行业制定了一系列碳减排组合机制。其中,碳排放权交易(以下简称“碳交易”)和绿色电力证书交易(以下简称“绿证…...

【原创】springboot+mysql海鲜商城设计与实现
个人主页:程序猿小小杨 个人简介:从事开发多年,Java、Php、Python、前端开发均有涉猎 博客内容:Java项目实战、项目演示、技术分享 文末有作者名片,希望和大家一起共同进步,你只管努力,剩下的交…...

envi5.6+SARscape560安装(CSDN_20240623)
envi和SARscape的版本必须匹配,否则有些功能不能使用。 Envi5.6安装 1. 点击安装程序. 2. 进入安装界面,点击“Next”. 3. 选择“I accept the agreement”,点击“Next”。 4. 选择安装路径,建议直接安装在默认路径下࿰…...

基本循环神经网络(RNN)
RNN背景:RNN与FNN 在前馈神经网络中,信息的传递是单向的,这种限制虽然使得网络变得更容易学习,但在一定程度上也减弱了神经网络模型的能力。 在生物神经网络中,神经元之间的连接关系要复杂的多。前馈神经网络可以看着…...

win32API(CONSOLE 相关接口详解)
前言: Windows这个多作业系统除了协调应⽤程序的执⾏、分配内存、管理资源之外,它同时也是⼀个很⼤的服务中⼼,调⽤这个服务中⼼的各种服务(每⼀种服务就是⼀个函数),可以帮应⽤程式达到开启视窗、描绘图形…...

python爬虫学习笔记一(基本概念urllib基础)
学习资料:尚硅谷_爬虫 学习环境: pycharm 一.爬虫基本概念 爬虫定义 > 解释1:通过程序,根据URL进行爬取网页,获取有用信息 > 解释2:使用程序模拟浏览器,向服务器发送请求,获取相应信息…...

MyBatis映射器:一对多关联查询
大家好,我是王有志,一个分享硬核 Java 技术的金融摸鱼侠,欢迎大家加入 Java 人自己的交流群“共同富裕的 Java 人”。 在学习完上一篇文章《MyBatis映射器:一对一关联查询》后,相信你已经掌握了如何在 MyBatis 映射器…...

100多个ChatGPT指令提示词分享
当前,ChatGPT几乎已经占领了整个互联网。全球范围内成千上万的用户正使用这款人工智能驱动的聊天机器人来满足各种需求。然而,并不是每个人都知道如何充分有效地利用ChatGPT的潜力。其实有许多令人惊叹的ChatGPT指令提示词,可以提升您与ChatG…...

vue2和vue3数据代理的区别
前言: vue2 的双向数据绑定是利⽤ES5的⼀个 API ,Object.defineProperty( )对数据进行劫持结合发布订阅模式的方式来实现的。 vue3 中使⽤了 ES6的Proxy代理对象,通过 reactive() 函数给每⼀个对象都包⼀层Proxy,通过 Proxy监听属…...

已解决ApplicationException异常的正确解决方法,亲测有效!!!
已解决ApplicationException异常的正确解决方法,亲测有效!!! 目录 问题分析 出现问题的场景 报错原因 解决思路 解决方法 分析错误日志 检查业务逻辑 验证输入数据 确认服务器端资源的可用性 增加对特殊业务情况的处理…...

「前端+鸿蒙」鸿蒙应用开发-常用UI组件-图片-参数
在鸿蒙应用开发中,图片组件是展示图像的关键UI元素。以下是详细介绍图片组件的三个主要参数:图片尺寸、图片缩放和图片插值,并提供相应的示例代码。 图片尺寸 图片尺寸指的是图片组件在界面上显示的宽度和高度。你可以使用像素(px)或其他单位来指定尺寸。 width: 设置图片…...

Tobii Pro Lab 1.232是全球领先的眼动追踪研究实验软件
Tobii Pro Lab是全球领先的眼动追踪研究实验软件。软件功能强大且拥有友好的用户界面,使眼动追踪研究变得更加简单、高效。该软件提供了很高的灵活性,可运行高级实验,深入了解注意力和认知过程。 获取软件安装包以及永久授权联系邮箱:289535…...

【flink实战】flink-connector-mysql-cdc导致mysql连接器报类型转换错误
文章目录 一. 报错现象二. 方案二:重新编译打包flink-connector-cdc1. 排查脚本2. 重新编译打包flink-sql-connector-mysql-cdc-2.4.0.jar3. 测试flink环境 三. 方案一:改造flink连接器 一. 报错现象 flink sql任务是:mysql到hdfs的离线任务&…...

【Linux】系统文件IO·文件描述符fd
前言 C语言文件接口 C 语言读写文件 1.C语言写入文件 2.C语言读取文件 stdin/stdout/stderr 系统文件IO 文件描述符fd: 文件描述符分配规则: 文件描述符fd: 前言 我们早在C语言中学习关于如何用代码来管理文件,比如文件的…...

【计算机网络篇】数据链路层(6)共享式以太网_网络适配器_MAC地址
文章目录 🍔网络适配器🍔MAC地址🗒️IEEE 802局域网的MAC地址格式📒IEEE 802局域网的MAC地址发送顺序🥚单播MAC地址🥚广播MAC地址🥚多播MAC地址🔎小结 🍔网络适配器 要将…...

导入别人的net文件报红问题sdk
1. 使用cmd命令 dotnet --info 查看自己使用的SDK版本 2.直接找到项目中的 global.json 文件,右键打开,直接修改版本为本机的SDK版本,就可以用了...

LangChain 介绍
In recent times, you would probably have heard of many AI applications, one of them being chatpdf.com. 在最近,你可能听说过很多的AI应用,chatpdf.com就是其中的一个。 On this website, you can upload your own PDF. After uploading, you ca…...

【区分vue2和vue3下的element UI Avatar 头像组件,分别详细介绍属性,事件,方法如何使用,并举例】
在 Vue 2 的 Element UI 和 Vue 3 的 Element Plus 中,Avatar 头像组件可能并没有直接作为官方组件库的一部分。然而,为了回答你的问题,我将假设 Element UI 和 Element Plus 在未来的版本中可能添加了 Avatar 组件,或者我们将使用…...

数据分析必备:一步步教你如何用matplotlib做数据可视化(10)
1、Matplotlib 二维箭头图 箭头图将速度矢量显示为箭头,其中分量(u,v)位于点(x,y)。 quiver(x,y,u,v)上述命令将矢量绘制为在x和y中每个对应元素对中指定的坐标处的箭头。 参数 下表列出了quiver()函数的参数 - x - 1D或2D阵列,…...

Stable Diffusion部署教程,开启你的AI绘图之路
本文环境 系统:Ubuntu 20.04 64位 内存:32G 环境安装 2.1 安装GPU驱动 在英伟达官网根据显卡型号、操作系统、CUDA等查询驱动版本。官网查询链接https://www.nvidia.com/Download/index.aspx?langen-us 注意这里的CUDA版本,如未安装CUD…...

三生随记——诡异的牙线
在小镇的角落,坐落着一间古老的牙医诊所。这所诊所早已荒废多年,窗户上爬满了藤蔓,门板上的油漆斑驳脱落,仿佛诉说着无尽的沉寂与孤独。然而,在午夜时分,偶尔会有低沉的呻吟声从紧闭的诊所里传出࿰…...

批量重命名神器揭秘:一键实现文件夹随机命名,自定义长度轻松搞定!
在数字化时代,我们经常需要管理大量的文件夹,尤其是对于那些需要频繁更改或整理的文件来说,给它们进行批量重命名可以大大提高工作效率。然而,传统的重命名方法既繁琐又耗时,无法满足高效工作的需求。今天,…...

学习笔记——路由网络基础——路由转发
六、路由转发 1、最长匹配原则 最长匹配原则 是支持IP路由的设备默认的路由查找方式(事实上几乎所有支持IP路由的设备都是这种查找方式)。当路由器收到一个IP数据包时,会将数据包的目的IP地址与自己本地路由表中的表项进行逐位(Bit-By-Bit)的逐位查找,…...

Python网络安全项目开发实战,如何防命令注入
注意:本文的下载教程,与以下文章的思路有相同点,也有不同点,最终目标只是让读者从多维度去熟练掌握本知识点。 下载教程: Python网络安全项目开发实战_防命令注入_编程案例解析实例详解课程教程.pdf 在Python网络安全项目开发中,防止命令注入(Command Injection)是一项…...

程序员如何高效读代码?
程序员高效读代码的技巧包括以下几点: 明确阅读目的:在开始阅读代码之前,先明确你的阅读目的。是为了理解整个系统的架构?还是为了修复一个具体的bug?或者是为了了解某个功能是如何实现的?明确目的可以帮助…...

全面分析一下前端框架Angular的来龙去脉,分析angular的技术要点和难点,以及详细的语法和使用规则,底层原理-小白进阶之路
Angular 前端框架全面分析 Angular 是一个由 Google 维护的开源前端框架。它最早在 2010 年发布,最初版本称为 AngularJS。2016 年,团队发布了一个完全重写的版本,称为 Angular 2,之后的版本(如 Angular 4、Angular 5…...

VACUUM 剖析
VACUUM 剖析 为什么需要 Vacuum MVCC MVCC:Multi-Version Concurrency Control,即多版本并发控制。 PostgreSQL 使用多版本并发控制(MVCC)来支持高并发的事务处理,同时保持数据的一致性和隔离性。MVCC 是一种用于管…...

基于LangChain框架搭建知识库
基于LangChain框架搭建知识库 说明流程1.数据加载2.数据清洗3.数据切分4.获取向量5.向量库保存到本地6.向量搜索7.汇总调用 说明 本文使用openai提供的embedding模型作为框架基础模型,知识库的搭建目的就是为了让大模型减少幻觉出现,实现起来也很简单&a…...

LeetCode 1789, 6, 138
目录 1789. 员工的直属部门题目链接表要求知识点思路代码 6. Z 字形变换题目链接标签思路代码 138. 随机链表的复制题目链接标签思路代码 1789. 员工的直属部门 题目链接 1789. 员工的直属部门 表 表Employee的字段为employee_id,department_id和primary_flag。…...