MySQL压缩表就是通过调整KEY_BLOCK_SIZE大小(可选1、2、、4/8/16)压缩表或特定算法(如zlib、lz4、zstd)压缩页,对表中的数据和索引进行无损压缩,减少磁盘存储占用的一种表优化方式。
做后端开发、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负担。
如果处理不当,会出现如下错误:
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.或者:
ERROR 1030 (HY000): Got error -1 from storage engine文件格式如果是老的格式(老版本物理方式原地升级),则可能会报如下错误:
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。
查看当前表的行格式:
show table status like 'tb2';对该表进行压缩。
alter table tb2 row_format='compressed';压缩后,空间降至232M。
2. 页压缩
MySQL8.0 中选取一张表,压缩前占用空间68M。

通过页压缩方式处理:
mysql> alter table orders COMPRESSION='zlib', ALGORITHM = INPLACE, LOCK = NONE;执行完空间如下:
可以看出,空间并没有降低,主要原因是该命令只修改了表的元数据,仅对后续新增的数据启用压缩,而不会压缩表中已有的存量数据,需要重建表来压缩存量数据。
因此进行优化(重建)处理:
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+优先页压缩)、避开坑点(不盲目压缩高并发表)。