InnoDB压缩技术:节省空间提升性能
这段内容来自 MySQL 官方文档的 第 17.9 节:InnoDB 表和页压缩(InnoDB Table and Page Compression),主要介绍 InnoDB 提供的两种数据压缩技术:表压缩(Table Compression) 和 页压缩(Page Compression),后者也叫 透明页压缩(Transparent Page Compression)。
我们来一步步通俗地解释这段内容,让你彻底理解这两个功能的作用、区别和价值。
🎯 一句话总结
InnoDB 支持两种压缩方式:
- 表压缩(Table Compression):传统压缩,节省空间但性能开销较大
- 页压缩(Page Compression):现代透明压缩,性能更好,推荐使用(尤其是 SSD)
它们都能 减少磁盘和内存中的数据量,提升性能、节省空间,特别适合 SSD 存储和带索引的大表。
🔍 一、为什么要压缩?—— 压缩的好处
文档说:
“Compression can help to improve both raw performance and scalability.”
意思是:压缩不仅能省空间,还能提升性能和可扩展性!
✅ 压缩的三大好处:
好处 | 说明 |
---|---|
📉 节省磁盘空间 | 数据文件 .ibd 更小,降低存储成本 |
🚀 减少 I/O | 读写更少的数据块,尤其是从磁盘到内存 |
🧠 提高缓存效率 | 同样大小的 Buffer Pool 能缓存更多数据,命中率更高 |
📌 特别对 有二级索引的表 效果更明显:
- 索引也被压缩 → 索引更小 → 查询更快
- 更多索引页能放进内存 → 减少磁盘查找
💡 为什么对 SSD 尤其重要?
- SSD 容量通常比 HDD 小
- SSD 价格更高($/GB)
- 压缩 = 更大有效容量 + 更长 SSD 寿命(减少写放大)
🔧 二、两种压缩方式对比
InnoDB 提供了两种不同的压缩机制:
特性 | 表压缩(Table Compression) | 页压缩(Page Compression / 透明压缩) |
---|---|---|
引入版本 | 较早(MySQL 5.7+) | MySQL 8.0.20+(推荐) |
别名 | 常规压缩、压缩表 | 透明页压缩(Transparent Page Compression) |
压缩单位 | 页内压缩(但逻辑上是表级) | 物理页压缩(直接写入磁盘) |
压缩算法 | zlib (默认) | zlib , lz4 , zstd (可选) |
是否透明 | 否(需显式指定 ROW_FORMAT=COMPRESSED ) | 是(几乎透明,只需 COMPRESSION 属性) |
性能 | 一般,压缩/解压开销较高 | 更好,I/O 更少,延迟更低 |
适用场景 | 老版本,冷数据归档 | 新项目,高性能 OLTP,SSD |
📦 三、1. 表压缩(InnoDB Table Compression)
📌 原理:
- 数据以 压缩页 形式存储(如 8KB 压缩成 4KB)
- 使用
zlib
算法压缩每个页 - 解压发生在 Buffer Pool 中(读取时)
✅ 如何启用?
CREATE TABLE t1 (id INT PRIMARY KEY,data VARCHAR(100)
) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
ROW_FORMAT=COMPRESSED
:启用压缩KEY_BLOCK_SIZE
:指定压缩后的页大小(单位 KB),可选值:1, 2, 4, 8(KB)
例如:
KEY_BLOCK_SIZE=8
表示目标压缩页大小为 8KB(原始 16KB 页压缩到 8KB)
⚠️ 缺点:
- 压缩/解压在 CPU 上进行,增加负载
- 不支持所有页类型(如 undo log)
- 配置稍复杂
🧼 四、2. 页压缩 / 透明页压缩(InnoDB Page Compression)
📌 原理:
- 更底层的压缩,由文件系统或存储引擎直接支持
- 写入磁盘前,InnoDB 尝试将整个页压缩
- 如果压缩失败(如无法压缩),就以原始大小写入
- 使用现代算法:
zlib
,lz4
,zstd
(更快或更高压缩比)
✅ 如何启用?
CREATE TABLE t1 (id INT PRIMARY KEY,data VARCHAR(100)
) COMPRESSION="zlib";
或者修改现有表:
ALTER TABLE t1 COMPRESSION="zstd";
支持的算法:
"zlib"
:兼容性好,压缩比高"lz4"
:速度极快,压缩比中等"zstd"
:现代算法,平衡速度与压缩比(推荐)
✅ 为什么叫“透明”?
- 对应用完全透明,无需改 SQL
- 自动处理压缩/解压
- 即使某些页无法压缩,也能正常工作
✅ 优势:
- 更好的 I/O 性能(尤其是 SSD)
- 支持动态切换压缩算法
- 与 DDL 操作兼容性更好
- 减少写放大(对 SSD 友好)
📊 五、实际效果示例
假设你有一个 100GB 的大表:
压缩方式 | 预估空间占用 | I/O 减少 | 适用场景 |
---|---|---|---|
不压缩 | 100GB | - | 无 |
表压缩 | 50~70GB | 3050% | 冷数据、归档 |
页压缩(zstd) | 40~60GB | 4060% | 在线交易、高并发 |
📌 Buffer Pool 效果:
- 原本 20GB Buffer Pool 只能缓存 20% 数据
- 压缩后可缓存 40~50% → 查询命中率大幅提升!
⚠️ 六、注意事项和限制
注意点 | 说明 |
---|---|
🔹 CPU 开销 | 压缩/解压需要 CPU 资源,确保 CPU 不成为瓶颈 |
🔹 压缩率取决于数据 | 文本、日志类数据压缩率高;加密或二进制数据难压缩 |
🔹 不是所有表都适合 | 小表、频繁更新的热表可能收益不大 |
🔹 备份和恢复 | 压缩表备份文件也更小,但恢复时仍需解压 |
🔹 监控压缩效果 | 可通过 INFORMATION_SCHEMA.INNODB_CMP 等表查看压缩统计 |
✅ 七、最佳实践建议
场景 | 推荐方案 |
---|---|
✅ 新项目,MySQL 8.0.20+ | 使用 页压缩(COMPRESSION=“zstd”) |
✅ SSD 存储 | 强烈推荐启用压缩,节省空间 + 延长寿命 |
✅ 大表、带索引的表 | 压缩收益最大 |
✅ 冷数据归档 | 可用表压缩(兼容老版本) |
✅ 高并发 OLTP | 选择 lz4 或 zstd ,平衡速度与压缩比 |
🔍 不确定是否该压缩? | 先在测试环境对比性能和空间使用 |
📌 八、如何查看压缩状态?
查询表的压缩信息:
SELECT TABLE_NAME, CREATE_OPTIONS
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'your_db' AND TABLE_NAME = 't1';
输出示例:
TABLE_NAME: t1
CREATE_OPTIONS: COMPRESSION="zstd"
查看压缩统计(表压缩):
SELECT * FROM INFORMATION_SCHEMA.INNODB_CMP;
显示压缩页的尝试次数、成功次数、压缩率等。
✅ 总结:关键要点
要点 | 说明 |
---|---|
🔹 两种压缩 | 表压缩(老) vs 页压缩(新/推荐) |
🔹 核心好处 | 省空间、减 I/O、提性能、增缓存命中率 |
🔹 特别适合 | SSD、大表、带索引的表 |
🔹 页压缩优势 | 透明、高效、支持现代算法(zstd/lz4) |
🔹 启用方式 | COMPRESSION="zstd" (简单!) |
🔹 注意 CPU | 压缩需要 CPU 资源,避免过载 |
🔹 推荐算法 | zstd (平衡)或 lz4 (极速) |
💡 一句话建议:
如果你用的是 MySQL 8.0.20+,并且有 大表或 SSD 存储,强烈建议尝试 透明页压缩(
COMPRESSION="zstd"
),它能显著节省空间并提升性能,而且配置极其简单。
需要我帮你写一个脚本,分析哪些表最适合开启压缩吗?