MySQL磁盘碎片整理实例演示

目录
  • 1.磁盘碎片是什么
  • 2.实验
  • 3.对于碎片回收操作
  • 4.后记
  • 补充:如何优化磁盘空间

数据库引擎以InnoDB为主

1.磁盘碎片是什么

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

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

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

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

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

InnoDB后台线程:https://www.jb51.net/article/243211.htm

解释磁盘碎片的英文博客: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

创建后的磁盘存储大小:

​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:

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

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

下面我们执行删除操作:

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

文件大小:

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

可以看到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结果

磁盘文件小了一半左右

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。

参考博客:https://www.jb51.net/article/223238.htm --写的很好,就是排版不舒服

https://www.jb51.net/article/243217.htm --写的不错

补充:如何优化磁盘空间

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碎片整理内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MySQL 清除表空间碎片的实例详解

    MySQL 清除表空间碎片的实例详解 碎片产生的原因 (1)表的存储会出现碎片化,每当删除了一行内容,该段空间就会变为空白.被留空,而在一段时间内的大量删除操作,会使这种留空的空间变得比存储列表内容所使用的空间更大: (2)当执行插入操作时,MySQL会尝试使用空白空间,但如果某个空白空间一直没有被大小合适的数据占用,仍然无法将其彻底占用,就形成了碎片: (3)当MySQL对数据进行扫描时,它扫描的对象实际是列表的容量需求上限,也就是数据被写入的区域中处于峰值位置的部分: 例如: 一个表有1万行

  • mysql sharding(碎片)介绍

    1.Sharding 的应用场景一般都那些? 当数据库中的数据量越来越大时,不论是读还是写,压力都会变得越来越大.试想,如果一张表中的数据量达到了千万甚至上亿级别的时候,不管是建索引,优化缓存等,都会面临巨大的性能压力.sharding通过某种条件,把同一个数据库中的数据分散到多个数据库或多台机器上,以减小单台机器压力. 联机游戏.IM.BSP 都是比较适合 Sharding 的应用场景: 2.Sharding与数据库分区(Partition)的区别? sharding实现了数据的分布式部署,将

  • MySQL 表空间碎片的概念及相关问题解决

    背景 经常使用 MySQL 的话,会发现 MySQL 数据文件的磁盘空间一般会不停的增长,而且有时候删了数据或者插入一批数据的时候,磁盘空间有时候还会毫无变化.引发这个其妙现象的就是 MySQL 的表空间碎片. 什么是表空间碎片? 表空间碎片指的是表空间中存在碎片,形象一点来比喻的话,就像是一张 A4 纸,"表空间碎片"就像是把这张 A4 纸撕碎,再重新拼起来,各个碎片之间都会有一些缝隙存在,这些缝隙就是"表空间碎片".重新拼起来的碎片实际上会比完整的 A4 纸大上

  • MySQL表的碎片整理和空间回收的方法

    目录 MySQL表碎片化(Table Fragmentation)的原因 行碎片(Row fragmentation) 行间碎片(Intra-row fragmentaion) 剩余空间碎片(Free space fragmentation) MySQL中如何找出碎片化严重的表 方法1:使用show table status from xxxx like 'xxxx' \G; 方法2:查询information_schema.TABLES获取表的碎片化信息. MySQL中如何减低表的碎片 OPT

  • 解析mysql 表中的碎片产生原因以及清理

    大量删除数据必然会在数据文件中造成不连续的空白空间,而当插入数据时,这些空白空间则会被利用起来 .对于不同的存储引擎整理碎片的方式不一样.myisam可以有以下方式:mysql> show table status from test like 'testusers'\G*************************** 1. row ***************************  ....           Rows: 3 Avg_row_length: 45        

  • MySQL磁盘碎片整理实例演示

    目录 1.磁盘碎片是什么 2.实验 3.对于碎片回收操作 4.后记 补充:如何优化磁盘空间 数据库引擎以InnoDB为主 1.磁盘碎片是什么 ​InnoDB表的数据存储在页中,每个页可以存放多条记录,这些记录以树形结构组织,这棵树称为B+树. ​聚簇索引的叶子结点包含行中所有字段的值,辅助索引的叶子结点包含索引列和主键列. ​在InnoDB中,删除一些行,这些行只是被标记已删除,而不会立即删除,个人认为和电脑的清除磁盘相同,之后可以通过覆盖旧数据实现删除,InnDB的Purge线程会异步的清理这

  • MYSQL优化之数据表碎片整理详解

    目录 在MySQL中,我们经常会使用VARCHAR.TEXT.BLOB等可变长度的文本数据类型.不过,当我们使用这些数据类型之后,我们就不得不做一些额外的工作——MySQL数据表碎片整理. 那么,为什么在使用这些数据类型之后,我们就要对MySQL定期进行碎片整理呢? 现在,我们先来看一个具体的例子.在这里,我们使用如下SQL语句在MySQL自带的TEST数据库中创建名为DEMO的数据表并插入5条测试数据. --创建DEMO表 CREATE TABLE DEMO( id int unsigned,

  • XP中如何完成一次全面的碎片整理

    内容提要:Hiberfil.sys文件的存在会使得系统无法完成一次全面的磁盘碎片整理,本文将介绍如何在磁盘碎片整理前先删除Hiberfil.sys文件. 现在许多Windows XP用户已经习惯于使用系统提供的休眠功能,因为这样可以省去开关机的时间,而且每次开机时可以直接恢复到原来的工作状态,比如原先正在写作的一篇文章或正在绘制的一副图画等.然而不知你注意到没有,休眠虽然有这样的好处,但也会带来一些小小的不便. 如果你定期地对硬盘进行磁盘碎片整理,并且整理完成后查看了碎片整理报告,可能会注意到,

  • MySQL参数调优实例探究讲解

    目录 一.MySQL 参数调优 1.一些生产常用查询命令 2.分析慢查询 3.分析连接数 4.缓冲区调优 Key_buffer_size 5.临时表调优 Created_tmp_tables 6.分析 Open Table 使用情况 7.查看 MySQL进程使用情况 8.查询缓存 query cache 9.分析SQL排序与锁及文件使用与表扫描情况 二.MySQL优化参数实战 总结 一.MySQL 参数调优 1.一些生产常用查询命令 -- 查看数据库里正在执行的sql语句 show proces

  • MyBatis配置文件解析与MyBatis实例演示

    MyBatis介绍 MyBatis是一个持久层的ORM框架,使用简单,学习成本较低.可以执行自己手写的SQL语句,比较灵活.但是MyBatis的自动化程度不高,移植性也不高,有时从一个数据库迁移到另外一个数据库的时候需要自己修改配置,所以称只为半自动ORM框架 传统JDBC和Mybatis相比的弊病 传统JDBC @Test public void test() throws SQLException { Connection conn=null; PreparedStatement pstmt

  • MySQL事务与锁实例教程详解

    目录 MySQL事务和锁 事务 事务的控制语句 事务隔离级别设置 脏读 不可重复读 幻读 锁机制 InnoDB的行级锁 锁实战 死锁 总结 MySQL事务和锁 事务 说到关系型的数据库的事务,相信大家对四大特性都不陌生,分别是原子性.一致性.隔离性.持久性,简称为ACID特性. MySQL中支持3种不同的存储引擎: MyISAM存储引擎.Memory存储引擎.和InnoDB存储引擎 注:只有InnoDB才支持事务. 事务的控制语句 控制语句 作用 begin或者start transaction

  • Delphi实例演示Rect、Bounds生成TRect的区别

    本文以实例演示Rect.Bounds生成TRect的区别,实例代码如下: unitUnit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type TForm1 = class(TForm) Button1: TButton; RadioGroup1: TRadioGroup; procedure Ra

  • mysql数据存储过程参数实例详解

    MySQL 存储过程参数有三种类型:in.out.inout.它们各有什么作用和特点呢? 一.MySQL 存储过程参数(in) MySQL 存储过程 "in" 参数:跟 C 语言的函数参数的值传递类似, MySQL 存储过程内部可能会修改此参数,但对 in 类型参数的修改,对调用者(caller)来说是不可见的(not visible). drop procedure if exists pr_param_in; create procedure pr_param_in ( in id

随机推荐