MySQL磁盘占用太多的一种优化思路

2022-01-25 18:45:27 浏览数 (1)

MySQL磁盘占用太多的一种优化思路

今天分享一个线上的经典MySQL磁盘问题。

01

背景介绍

线上的MySQL实例在使用时间长了之后,会保存很多的业务数据,通常情况下,磁盘使用量也会随着业务的接入时间上升。

对于InnoDB存储引擎来说,如果业务部门的SQL有大量的随机insert和delete操作,那么会导致这个数据表中有很多空洞,删除了部分数据之后,磁盘空间并不会立即释放,这个问题的原因是delete数据仅仅是在数据记录的位置打上一个delete标识,并不会真正的删除数据。这样,表中就形成了一个一个的"空洞",随着时间变长,表中的空洞会越来越多。我曾经遇到过,一个表保存了1w条左右的数据,但是容量达到了40GB,这明显是不正常的。

针对上面这个问题,其实我们可以使用下面的方法来处理:

alter table tbl_name engine=innodb;

或者:

optimize table tbl_name;

但是,今天我们讨论的,不是这个问题,如果你做了alter table之后,磁盘空间还是不够用,怎么办

今天在线上就遇到了这样一个问题,答案是:修改存储引擎为tokudb

02

Tokudb存储引擎

Tokudb是一个比较冷门的引擎,但是它有很多优点,例如支持事务、支持MVCC、有着很高的数据压缩比,目前由percona公司负责维护。

Percona公司,搞MySQL的应该都听过,它是MySQL的两大分支中很重要的一个,也是大名鼎鼎的PT工具的母公司。Percona MySQL Server上就自带TokuDB这个存储引擎。

MySQL的插件式存储引擎设计,允许我们在线将innodb的存储引擎修改为tokudb的存储引擎。

我们修改innodb存储引擎为tokudb存储引擎的目的是想使用tokudb的高压缩比,那么这个压缩比有多大收益呢?来看我的测试:

1、查看表的数据量,并直接使用SQL语法修改,如下:

代码语言:javascript复制
mysql > select count(1) from table_name ;
 ---------- 
| count(1) |
 ---------- 
|  6313530 |
 ---------- 
1 row in set (1.70 sec)

mysql > alter table table_name engine=tokudb;
Query OK, 6313530 rows affected (21 min 42.91 sec)
Records: 6313530  Duplicates: 0  Warnings: 0

数据量大概631w,修改时间大概20min左右,很明显,它不是online DDL的,当然,你可以使用pt-osc工具去操作。

针对这个alter table修改时间20min,其实已经比较长了,在这个过程中,我们可以用另外的mysql shell,使用show processlist命令去查看alter table的执行进度,其实进度展示还是比较友好的,如下:

  • 加载ibd文件的速度展示:

Loading of data t ./table_name/#sql-5063_310d24f1 about 77.6% done | alter table table_name engine=tokudb

这里可以看到进度是77.6%

  • 加载完毕后的唯一性校验

Verifying index uniqueness: Checked 4600000 of 0 rows in key-PRIMARY. | alter table table_name engine=tokudb

2、查看修改前后的磁盘收益:

代码语言:javascript复制
[root ]# ll | grep table_name
-rw-r----- 1 my5500 mysql       43196 Feb 25  2021 table_name.frm
-rw-r----- 1 my5500 mysql 24482152448 Jan 11 15:58 table_name.ibd
简单计算下ibd文件的容量
mysql > select 24482152448/1024/1024/1024;
 ---------------------------- 
| 24482152448/1024/1024/1024 |
 ---------------------------- 
|            22.800781250000 |
 ---------------------------- 
1 row in set (0.00 sec)
修改前,innodb累积:22.8 G
-------------------------分割线-----------------------
[root ]# du -sh -c table_name*  
44K     table_name.frm
117M    table_name_key_ch_gr_7ee403500_2_1d.tokudb
129M    table_name_key_idx_xxx_7ee403500_3_1d.tokudb
129M    table_name_key_idx_xxx_7ee403500_4_1d.tokudb
129M    table_name_key_idx_xxx_7ee403500_6_1d.tokudb
129M    table_name_key_idx_xxx_7ee403500_5_1d.tokudb
122M    table_name_key_idx_xxx_time_7ee403500_7_1d.tokudb
170M    table_name_key_idx_xxx_cmnt_7ee403500_8_1d.tokudb
127M    table_name_key_idx_xxx_time_7ee403500_9_1d.tokudb
121M    table_name_key_m_xxx_xxx_7ee403500_a_1d.tokudb
121M    table_name_key_m_xxx_7ee403500_b_1d.tokudb
123M    table_name_key_m_time_7ee403500_c_1d.tokudb
1.4G    table_name_main_7ee403500_d_1d.tokudb
32K     table_name_status_7ee403500_e_1d.tokudb
2.8G    total

修改后,tokudb累积:2.8G

不难看出,修改之前,innodb的数据量有22.8G,修改之后tokudb的数据量仅有2.8G

通过修改存储引擎为tokudb,压缩了8倍磁盘容量

03

tokudb这么好,为什么还要用innodb呢?

既然tokudb的也支持事务,也支持mvcc,占用的磁盘还少,那为什么还要使用innodb呢?

1、试想这样一个问题,tokudb高压缩比的存储方法,其实在磁盘上存储的文件已经是压缩过了的,如果我们访问的数据在内存中,那么访问innodb和tokudb的时间差不多;

但如果我们访问的数据在磁盘上,那么tokudb要先将压缩的数据解压,然后在存入内存中访问,这个解压的过程是有代价的,需要消耗CPU,也会带来一定的时延,因此,性能上会有损耗

如果业务对性能要求比较高,可能不太合适。

2、其次,tokudb是需要使用percona版本的MySQL Server的,社区版本并不支持。可能需要调整线上的MySQL服务版本。

3、其他一些Innodb的新特性。

总之:

如果你的业务对MySQL访问性能要求不高,但是数据量非常大,建议使用tokudb,它可以帮你节省磁盘空间;

如果你的业务对性能要求也高,数据量也比较大,建议直接扩充磁盘,或者上tidb吧。。。

0 人点赞