首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >MySQL磁盘告急?表压缩实操,不扩容也能解决磁盘爆满问题

MySQL磁盘告急?表压缩实操,不扩容也能解决磁盘爆满问题

作者头像
俊才
发布2026-03-31 12:21:09
发布2026-03-31 12:21:09
1280
举报
文章被收录于专栏:数据库干货铺数据库干货铺

做后端开发、DBA的同学,大概率都遇到过这样的困境:数据库磁盘告急,日志表、历史归档表越存越大,扩容成本高不说,还拖慢IO性能;备份耗时越来越久,甚至影响业务正常运行。

其实不用急着扩容,MySQL自带的压缩表功能,就能轻松解决这个问题,并且以CPU小幅开销,换磁盘空间大幅节省,最高能省70%,还能间接提升IO效率。

一、先搞懂:MySQL压缩表到底是什么

简单说,MySQL压缩表就是通过调整KEY_BLOCK_SIZE大小(可选1、2、、4/8/16)压缩表或特定算法(如zlib、lz4、zstd)压缩页,对表中的数据和索引进行无损压缩,减少磁盘存储占用的一种表优化方式。

核心原理很简单:数据库中的数据(尤其是文本、JSON、日志类数据)存在大量重复序列,压缩算法会找到这些重复序列并进行编码,存储时只保留一份编码信息,读取时再解码还原,全程不丢失任何数据。

1. 主要特点

MySQL的表进行压缩具备如下主要特点:

  • 无损压缩:压缩和解压过程完全可逆,不会导致数据丢失,这是数据库压缩的核心要求,也是和普通文件压缩的关键区别
  • 压缩方式:MySQL支持表压缩(ROW_FORMAT=COMPRESSED)和页压缩(COMPRESSION参数),前者兼容旧版本,后者是MySQL8.0.20+新增,更轻量化、不锁表
  • 核心特点:以CPU开销换磁盘空间——压缩/解压时会消耗少量CPU资源,适合读多写少的场景,不适合高并发写入的表(如实时交易表)

2. 适合压缩的表

不是所有表都适合压缩,如果出现数据库服务器磁盘空间不足且不宜扩容的情况下,优先压缩这些表:

  • 历史归档表、日志表(如操作日志、接口日志):数据写入后几乎不修改,读多写少,压缩收益最高
  • 大表(百万级+数据):包含大量TEXT、VARCHAR、JSON字段,重复数据多,压缩率可达40%-70%
  • 备份表、只读表:无需频繁写入,压缩后可大幅减少备份体积和存储成本

3. 不适合压缩的表

有些表强行压缩,会导致性能下降,甚至影响后续的写入(新增数据或加索引等会报错),例如下列这些表:

  • 高并发写入表(如订单表、用户行为表):频繁写入会反复压缩/解压,CPU负载飙升,写入延迟增加
  • 小表(万级以下数据):压缩收益甚微,反而浪费CPU资源
  • 包含大量BLOB、大二进制字段的表:这类数据压缩效果差,还会增加CPU负担

如果处理不当,会出现如下错误:

代码语言:javascript
复制
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting blobs, is 65535. 
This includes storage overhead, so the actual maximum row size is less.

或者

代码语言:javascript
复制
ERROR 1030 (HY000): Got error -1 from storage engine

文件格式如果是老的格式(老版本物理方式原地升级),则可能会报如下错误:

代码语言:javascript
复制
ERROR 1478 (HY000): InnoDB table 'db.tbl' has row_format=COMPRESSED but the innodb_file_format is Antelope. 
Support for COMPRESSED row format requires innodb_file_format=Barracuda.

二、 实操案例

1. 表行格式压缩

本次在MySQL5.7中选取一张超过1kw的表(tb2)

压缩前,磁盘空间占用632M

查看当前表的行格式:

代码语言:javascript
复制
show  table status like 'tb2';

对该表进行压缩

代码语言:javascript
复制
alter table tb2 row_format='compressed';

压缩后,空间降至232M

2. 页压缩

MySQL8.0 中选取一张表,压缩前占用空间68M

通过页压缩方式处理:

代码语言:javascript
复制
mysql> alter table orders COMPRESSION='zlib', ALGORITHM = INPLACE, LOCK = NONE;

执行完空间如下:

可以看出,空间并没有降低,主要原因是该命令只修改了表的元数据,仅对后续新增的数据启用压缩,而不会压缩表中已有的存量数据,需要重建表来压缩存量数据。

因此进行优化(重建)处理:

代码语言:javascript
复制
mysql> alter table orders engine =innodb;

重建后大小如下:

3. 压缩前后空间对比

压缩率是与当前表中存储的数据及压缩方式有关,本文中2个案例的压缩率如下:

状态

压缩前占用(MB)

压缩后占用(MB)

压缩率

行格式压缩

632

232

63.29%

页压缩(zlib)

68

52

23.53%

三、总结

MySQL压缩表,是以CPU小幅开销,换磁盘空间大幅节省的实用优化手段,尤其适合日志表、归档表等读多写少的大表,最高可省70%存储空间,还能减少IO压力、缩短备份时间。核心记住3点:选对场景(读多写少大表)、选对方式(8.0+优先页压缩)、避开坑点(不盲目压缩高并发表)

你在使用MySQL压缩表时,踩过哪些坑?或者有更好的优化技巧?欢迎在留言区交流。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-03-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据库干货铺 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档