必须开启innodb_file_per_table才能启用innodb表空间压缩,否则即使建表指定row_format=compressed也无效;需重启mysql并重建表生效,且仅5.7.9+原生支持,压缩效果需结合key_block_size与数据特征权衡。

innodb_file_per_table 必须开启,否则压缩无效
MySQL 的 InnoDB 表空间压缩只对独立表空间(即每个表一个 .ibd 文件)生效。如果 innodb_file_per_table 关闭,所有表都存进共享表空间 ibdata1,压缩配置会被忽略——哪怕你在 CREATE TABLE 里写了 ROW_FORMAT=COMPRESSED,也压不出任何效果。
检查方式:
SHOW VARIABLES LIKE 'innodb_file_per_table';返回
ON 才行。若为 OFF,需在 my.cnf 中添加:[mysqld] innodb_file_per_table = ON
注意:改完必须重启 MySQL;已有表不会自动迁移,需 ALTER TABLE t ENGINE=InnoDB; 重建才能进入独立表空间。
建表时指定 ROW_FORMAT=COMPRESSED 和 KEY_BLOCK_SIZE
InnoDB 压缩靠的是页级压缩(page-level),不是整表或列压缩。关键参数就两个:ROW_FORMAT=COMPRESSED 和 KEY_BLOCK_SIZE,后者决定压缩后页大小(单位 KB),常见值有 1、2、4、8、16(对应压缩后页尺寸)。
示例建表语句:
CREATE TABLE logs ( id BIGINT PRIMARY KEY, content TEXT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
-
KEY_BLOCK_SIZE必须是 1/2/4/8/16,其他值会报错Incorrect key_block_size - 实际压缩页大小不能大于
innodb_page_size(默认 16KB),所以KEY_BLOCK_SIZE=16等价于不压缩 - 压缩对 BLOB/TEXT/LONG VARCHAR 类型收益最大;纯 INT + VARCHAR(20) 这类短字段可能越压越大(因压缩头开销)
- 修改已有表压缩设置:用
ALTER TABLE t ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4;,但会锁表并重建
压缩失败的典型错误:"Unsupported compression algorithm" 或 "KEY_BLOCK_SIZE is not supported"
这两个错误通常指向同一个根源:MySQL 版本太低或未启用压缩支持模块。5.7.9+ 默认支持,但早期 5.7.x(如 5.7.6)需要手动加载 INFORMATION_SCHEMA.INNODB_CMP 相关引擎,而 5.6 完全不支持 ROW_FORMAT=COMPRESSED(只支持 innodb_file_format=Barracuda 下的页压缩,且需额外配置)。
验证方式:
SELECT * FROM INFORMATION_SCHEMA.INNODB_CMP;
如果报错 Table 'INFORMATION_SCHEMA.INNODB_CMP' doesn't exist,说明压缩监控未启用,大概率版本不满足或配置缺失。此时强行建表会直接报错,而不是静默降级。
- 5.6 用户请放弃
ROW_FORMAT=COMPRESSED,考虑升级或用应用层压缩(如存前 gzip) - 5.7.9+ 用户仍报错,检查是否误启用了
innodb_strict_mode=OFF—— 关闭时部分错误会被吞掉,导致行为不可预测 -
KEY_BLOCK_SIZE值必须与innodb_page_size兼容;比如innodb_page_size=4096时,最大只支持KEY_BLOCK_SIZE=4
压缩后的读写性能变化比想象中复杂
压缩节省磁盘和内存(buffer pool 可缓存更多页),但 CPU 要承担压缩/解压开销。真实影响取决于数据特征和负载类型:
- 高并发随机读场景下,压缩常能提升 QPS——因为更多热数据能塞进 buffer pool,减少磁盘 IO
- 大批量 INSERT / UPDATE 场景可能明显变慢,尤其当
KEY_BLOCK_SIZE设得太小(如 1 或 2),导致频繁页分裂和压缩失败重试 - 压缩页在 buffer pool 中以解压形式存在,所以内存占用不减少;真正省的是磁盘和刷脏页带宽
- 别迷信“越小越省”:实测
KEY_BLOCK_SIZE=4对日志类文本压缩率约 2.3x,=2却只有 2.1x,但 CPU 使用翻倍,得不偿失
最稳妥的做法是先在测试库用真实数据跑 SYSBENCH 或业务 SQL 压测,对比不同 KEY_BLOCK_SIZE 下的 QPS、avg_latency 和 innodb_buffer_pool_reads 指标。
压缩不是开关,是权衡——特别是 buffer pool 不够大、CPU 又吃紧的时候,容易把问题从磁盘 IO 转移到 CPU 瓶颈上,这点很容易被忽略。











