MySQL磁盘碎片整理实例演示


Posted in MySQL onApril 03, 2022

数据库引擎以InnoDB为主

1.磁盘碎片是什么

​InnoDB表的数据存储在页中,每个页可以存放多条记录,这些记录以树形结构组织,这棵树称为B+树。

MySQL磁盘碎片整理实例演示

​聚簇索引的叶子结点包含行中所有字段的值,辅助索引的叶子结点包含索引列和主键列。

​在InnoDB中,删除一些行,这些行只是被标记已删除,而不会立即删除,个人认为和电脑的清除磁盘相同,之后可以通过覆盖旧数据实现删除,InnDB的Purge线程会异步的清理这些没用的索引键和行。但是依然不会把这些释放出来的空间还给操作系统重新使用,因此会导致页面中存在很多空洞,如果表结构中包含动态长度字段,这些空间甚至无法被InnoDB重新用来存储新的行。

​另外严重的问题是删除数据会导致页page中出现空白空间,大量随机的Delete操作必然会在数据文件中造成不连续的空白空间,当插入数据时,这些空白空间则会被利用起来,造成了数据的物理存储顺序和逻辑的排序顺序不同,这就是数据碎片。

-- 查看全局变量Purge
show variables like 'innodb_purge_threads';

解释磁盘碎片的英文博客:https://lefred.be/content/overview-of-fragmented-mysql-innodb-tables/

上面这是个大能的博客,写的pretty good!

2.实验

我们首先创建一个具有一百条数据的表来进行实验:

delimiter //
create procedure insertt()
begin
	declare i int DEFAULT 0;
	while i<1000000 do
		insert into temp values(null,'a',1);
		set i:=i+1;
	end while;
end;
//
delimiter ;
drop PROCEDURE insertt;
-- 尝试插入一百万条数据
 
call insertt()
 
-- mysql版本5.7.36
> OK
> 时间: 838.706s

创建后的磁盘存储大小:

MySQL磁盘碎片整理实例演示

​DB:information_scheme中存放我们表的信息,通过下列命令来查看我们的磁盘碎片最大的前五名

-- 别人的博客中copy的,我的猪脑写不出来
SELECT CONCAT(table_schema, '.', table_name) as 'TABLE', 
       ENGINE, CONCAT(ROUND(table_rows / 1000000, 2), 'M')  ROWS, 
       CONCAT(ROUND(data_length / ( 1024 * 1024 * 1024 ), 2), 'G') DATA, 
       CONCAT(ROUND(index_length / ( 1024 * 1024 * 1024 ), 2), 'G') IDX, 
       CONCAT(ROUND(( data_length + index_length ) / ( 1024 * 1024 * 1024 ), 2), 'G') 'TOTAL SIZE', 
       ROUND(index_length / data_length, 2)  IDXFRAC, CONCAT(ROUND(( data_free / 1024 / 1024),2), 'MB') AS data_free 
FROM information_schema.TABLES  
ORDER BY data_length + index_length desc LIMIT 5;

result:

MySQL磁盘碎片整理实例演示

我们可以看到data_free,我们最高的free空间只有6MB

innodb_ruby工具可以直接在linux系统下运行查看.Ibd文件的结构,将B+tree以及磁盘使用暴露出来,但是我不会用,这里带上他的github链接: https://github.com/akopytov/sysbench

下面我们执行删除操作:

-- 删除前五十万条数据
delete from temp order by id LIMIT 500000

文件大小:

MySQL磁盘碎片整理实例演示

删除后,磁盘文件的大小并没有变化,因为删除产生了磁盘碎片,空白page残留在文件中,被删除的数据记录仍然被保持在MySQL的链接清单中,因此数据存储文件的大小并不会随着数据的删除而减小,我们再次使用上述操作查看data_free。

MySQL磁盘碎片整理实例演示

可以看到temp表的data_free增长了。

3.对于碎片回收操作

对MySQL进行碎片整理有两种方法:

OPTIMIZE TABLE

OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE table_name1 [, table_name2] ...

ALTER

ALTER TABLE table_name ENGINE = Innodb

OPTIMIZE可以同时对多个表格进行碎片整理,OPTIMIZE语句有两个可选的关键字:LOCAL和NO_WRITE_TO_BINLOG,默认是每次碎片整理都会被记录到BINlog二进制日志中去,如果带了关键字,就不会被记录到日志中去。

ALTER看起来是执行了一次空操作,重新设置了一遍数据库引擎,同时会进行碎片整理。

两种操作在一定程度是等价的。

使用optimize结果

MySQL磁盘碎片整理实例演示

磁盘文件小了一半左右

MySQL磁盘碎片整理实例演示

alter不再演示

4.后记

1.MySQL官方建议不要经常(每小时或每天)进行碎片整理,一般根据实际情况,只需要每周或者每月整理一次即可。

2.OPTIMIZE TABLE只对MyISAM,BDB和InnoDB表起作用,尤其是MyISAM表的作用最为明显。此外,并不是所有表都需要进行碎片整理,一般只需要对包含上述可变长度的文本数据类型的表进行整理即可。

3.在OPTIMIZE TABLE运行过程中,MySQL会锁定表。

4.默认情况下,直接对InnoDB引擎的数据表使用OPTIMIZE TABLE,可能会显示「 Table does not support optimize, doing recreate + analyze instead」的提示信息。这个时候,我们可以用mysqld --skip-new或者mysqld --safe-mode命令来重启MySQL,以便于让其他引擎支持OPTIMIZE TABLE。

补充:如何优化磁盘空间

1.优化前必看注意事项

①.优化表空间时,会造成锁表

数据量越大的表,优化耗时越长,百万条数据大约耗时30s(约25000-30000行/秒,此数据根据机器磁盘性能会有差异)。所以,在磁盘优化时,所有的增删操作将受限,请选择一个业务空档期执行。

②.间隔多久需要优化一次磁盘碎片?

Mysql官方不建议频繁进行碎片整理,比如每天都整理磁盘。可观测一次优化后,能撑多久才会产生比较大的碎片文件,然后根据这个周期,定制一个定期优化碎片的任务。

如:每周或每月凌晨3点定时清理碎片。

2.如何优化磁盘空间

判断你的数据表的引擎是什么

①.如果引擎是MyISAM,则可以通过下面SQL优化。

-- 优化表空间
optimize table tableName;

注:如果引擎是InnoDB,执行此SQL会提示:Table does not support optimize, doing recreate + analyze instead②.如果引擎是InnoDB,通过下列SQL可以代替optimize table xxx

-- 将表改为InnoDB数据库引擎
ALTER TABLE tableName ENGINE=InnoDB;

-- 分析表,查看表状态
ANALYZE TABLE tableName;

即通过重新将数据库引擎设置为InnoDB的方式,来优化磁盘空间。

到此这篇关于MySQL磁盘碎片整理的文章就介绍到这了,更多相关MySQL碎片整理内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
详解MySQL InnoDB存储引擎的内存管理
Apr 08 MySQL
MySQL优化之如何写出高质量sql语句
May 17 MySQL
MySQL 视图(View)原理解析
May 19 MySQL
正确使用MySQL update语句
May 26 MySQL
MySQL系列之开篇 MySQL关系型数据库基础概念
Jul 02 MySQL
MySQL系列之九 mysql查询缓存及索引
Jul 02 MySQL
一篇文章看懂MySQL主从复制与读写分离
Nov 07 MySQL
利用JuiceFS使MySQL 备份验证性能提升 10 倍
Mar 17 MySQL
详解Mysql事务并发(脏读、不可重复读、幻读)
Apr 29 MySQL
mysql查找连续出现n次以上的数字
May 11 MySQL
MySQL一劳永逸永久支持输入中文的方法实例
Aug 05 MySQL
关于MySQL中explain工具的使用
May 08 MySQL
Mysql使用全文索引(FullText index)的实例代码
Apr 03 #MySQL
一文简单了解MySQL前缀索引
为什么MySQL不建议使用SELECT *
详解MySQL的主键查询为什么这么快
MySQL表锁、行锁、排它锁及共享锁的使用详解
navicat 连接Ubuntu虚拟机的mysql的操作方法
MySQL中IO问题的深入分析与优化
You might like
有关PHP性能优化的介绍
2013/06/20 PHP
学习php设计模式 php实现访问者模式(Visitor)
2015/12/07 PHP
PHP中array_keys和array_unique函数源码的分析
2016/02/26 PHP
orm获取关联表里的属性值
2016/04/17 PHP
OfflineSave离线保存代码再次发布使用说明
2007/05/23 Javascript
Javascript的构造函数和constructor属性
2010/01/09 Javascript
js防止DIV布局滚动时闪动的解决方法
2014/10/30 Javascript
js中的事件捕捉模型与冒泡模型实例分析
2015/01/10 Javascript
js的window.showModalDialog及window.open用法实例分析
2015/01/29 Javascript
JavaScript获取URL汇总
2015/06/08 Javascript
xcode中获取js文件的路径方法(推荐)
2016/11/05 Javascript
js获取当前时间(昨天、今天、明天)
2016/11/23 Javascript
Angular.JS中指令ng-if、ng-show/ng-hide和ng-switch的使用教程
2017/05/07 Javascript
12个非常有用的JavaScript技巧
2017/05/17 Javascript
jQuery实现键盘回车搜索功能
2017/07/25 jQuery
快速解决angularJS中用post方法时后台拿不到值的问题
2018/08/14 Javascript
JavaScript事件发布/订阅模式原理与用法分析
2018/08/21 Javascript
利用vue.js把静态json绑定bootstrap的table方法
2018/08/28 Javascript
javascript如何使用函数random来实现课堂随机点名方法详解
2020/07/28 Javascript
Javascript数组及类数组相关原理详解
2020/10/29 Javascript
[01:02:09]Liquid vs TNC 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.21
2020/07/19 DOTA
python中通过预先编译正则表达式提高效率
2017/09/25 Python
python中reduce()函数的使用方法示例
2017/09/29 Python
关于Tensorflow中的tf.train.batch函数的使用
2018/04/24 Python
Python检测网络延迟的代码
2018/05/15 Python
解决pyshp UnicodeDecodeError的问题
2019/12/06 Python
ProForm英国站点:健身房和健身器材网上商店
2019/06/05 全球购物
微软马来西亚官方网站:Microsoft马来西亚
2019/11/22 全球购物
本科生学习总结的自我评价
2013/10/02 职场文书
送餐员岗位职责范本
2014/02/21 职场文书
副总经理岗位职责
2014/03/16 职场文书
医德医风演讲稿
2014/05/20 职场文书
解除聘用合同证明书范本
2014/09/11 职场文书
2015年收银工作总结范文
2015/04/01 职场文书
使用feign服务调用添加Header参数
2021/06/23 Java/Android
win10滚动条自动往上跑怎么办?win10滚动条自动往上跑的解决方法
2022/08/05 数码科技