当前位置: 首页 > news >正文

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操作也可能会导致页分裂,频繁地页分裂,页会变得稀疏,并且被不规则的填充,继而产生表碎片,

另外,表的数据存储也可能会碎片化,数据存储的碎片化比索引更加复杂,主要有三种类型的数据碎片:

  1. 行碎片(Row fragmetation)
    1. 指数据行被存储在多个地方的片段中,即使查询只从索引中访问一行记录,行碎片也会导致性能下降
  2. 行间碎片(Intra-row fragmetaion)
    1. 行间碎片是指逻辑上顺序的页或者行在磁盘上不是顺序存储的,行间碎片对诸如全表扫描和聚簇索引扫描之类的操作有很大的影响,因为这些操作原本能从磁盘顺序存储的数据中获益
  3. 剩余空间碎片(Free space fragmenation)
    1. 指数据页中有大量的空余空间,会导致服务器读取大量不需要的数据,从而造成浪费。

对于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工作原理如下:

  1. 如果表有删除或拆分行,则修复该表。
  2. 如果索引页未排序,则对其进行排序。
  3. 如果表的统计信息不是最新的(并且无法通过对索引进行排序来完成修复),则更新它们。

第二种操作则是使用ALTER TABLE table_name ENGINE= InnoDB; 的方式,此方式看起来没有执行什么操作,实际上重新整理碎片了,当执行这个优化操作时,InnoDB会重建整个表并释放聚簇索引中未使用的空间。

4. 小结

因为删除表数据发现表使用空间未被释放,继而发现有表碎片问题,查找一些资料去了解表碎片的产生以及表碎片的处理,最终让自己学习到了关于InnoDB表碎片相关的知识。

表碎片的产生主要是InnoDB删除非物理删除,而是标记”删除”,且这些被“删除”的空间后续还可复用,进而导致磁盘上索引页的物理顺序与页面上记录的索引顺序不接近,引发表的碎片化。同时表的大量更新、表的数据存储页都会产生不同的表碎片。

表碎片的清除手段:

  1. OPTIMIZE TABLE table_name;
  2. 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. 选择安装路径,建议直接安装在默认路径下&#xff0…...

基本循环神经网络(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阵列,…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

MySQL 主从同步异常处理

阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示&#xff…...

软件工程 期末复习

瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...