MySQL InnoDB表压缩:性能优化全解析
这段内容是 MySQL 官方文档 17.9.1 节:InnoDB 表压缩(InnoDB Table Compression) 的引言部分,它是一个子章节的总览,告诉你接下来要讲什么。
我们来一步步拆解、解释和通俗化这段内容,帮助你彻底理解 “InnoDB 表压缩” 是什么、怎么用、以及它在整个 MySQL 压缩体系中的定位。
🎯 一句话总结
InnoDB 表压缩 是一种通过
ROW_FORMAT=COMPRESSED
来启用的压缩技术,适用于使用 独立表空间(file-per-table)或通用表空间(general tablespace) 的 InnoDB 表。它的目标是 减少磁盘和内存中的数据量,提升性能和存储效率。
🔍 一、什么是 “InnoDB 表压缩”?
✅ 定义:
InnoDB 表压缩(Table Compression)是一种 在页级别对数据和索引进行压缩 的技术,压缩后的数据存储在磁盘上,读取时再解压到内存中。
📌 它不是“文件系统压缩”,而是 InnoDB 存储引擎原生支持的压缩机制。
📁 二、支持的表空间类型(重要前提)
文档强调:
“supported with InnoDB tables that reside in file_per_table tablespaces or general tablespaces”
意思是:只有以下两种表空间支持表压缩:
表空间类型 | 说明 |
---|---|
✅ file_per_table (独立表空间) | 每个表一个 .ibd 文件(默认开启) |
✅ 通用表空间(General Tablespace) | 多个表共享一个 .ibd 文件(MySQL 5.7+ 引入) |
❌ 系统表空间(ibdata1 ) | 不支持压缩! |
📌 所以,只要你的表是默认创建的(每个表一个 .ibd
文件),就可以使用表压缩。
🛠️ 三、如何启用表压缩?
使用 ROW_FORMAT=COMPRESSED
:
1️⃣ 创建表时启用
CREATE TABLE t1 (id INT PRIMARY KEY,name VARCHAR(100)
) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; -- 可选:目标压缩页大小(KB)
ROW_FORMAT=COMPRESSED
:启用压缩KEY_BLOCK_SIZE
:指定压缩后的页大小(单位 KB),可选值:1, 2, 4, 8
例如:
KEY_BLOCK_SIZE=8
表示希望将 16KB 的原始页压缩成 8KB 存储
2️⃣ 修改已有表
ALTER TABLE t1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
⚠️ 注意:ALTER TABLE
会重建表,可能耗时较长。
📚 四、接下来各小节内容预告(目录解析)
文档列出了 17.9.1 下的几个子章节,我们来解释每个部分讲什么:
🔹 17.9.1.1 Overview of Table Compression(概述)
- 介绍表压缩的基本概念
- 压缩的优缺点
- 适用场景(如 SSD、大表、只读数据等)
🔹 17.9.1.2 Creating Compressed Tables(创建压缩表)
- 详细语法:
CREATE TABLE ... ROW_FORMAT=COMPRESSED
KEY_BLOCK_SIZE
的含义和选择- 存储空间计算示例
- 如何选择合适的压缩页大小
🔹 17.9.1.3 Tuning Compression for InnoDB Tables(调优)
- 如何根据工作负载调整压缩设置
- 压缩比 vs CPU 开销的权衡
- 如何选择
KEY_BLOCK_SIZE
- 对 DML(INSERT/UPDATE/DELETE)性能的影响
🔹 17.9.1.4 Monitoring InnoDB Table Compression at Runtime(运行时监控)
- 如何查看压缩效果
- 使用
INFORMATION_SCHEMA.INNODB_CMP
和INNODB_CMP_PER_INDEX
表- 压缩尝试次数
- 成功次数
- 压缩失败原因
- 平均压缩比
📌 示例查询:
SELECT * FROM INFORMATION_SCHEMA.INNODB_CMP;
输出字段如:
page_size
:压缩页大小compress_ops
:压缩操作次数compress_ops_ok
:成功次数compress_time
/uncompress_time
:耗时
🔹 17.9.1.5 How Compression Works for InnoDB Tables(压缩原理)
- 底层机制:InnoDB 如何压缩和解压页
- 使用
zlib
算法 - 压缩发生在写入磁盘前,解压发生在读入 Buffer Pool 时
- 压缩页在内存中仍是解压状态
- 为什么不能压缩所有类型的页(如 undo log)
🔹 17.9.1.6 Compression for OLTP Workloads(OLTP 工作负载的压缩)
- OLTP(在线事务处理)通常是“读写频繁”
- 压缩可能增加 CPU 开销(每次读要解压,写要压缩)
- 但减少了 I/O,可能整体性能反而提升
- 建议:测试验证,选择合适
KEY_BLOCK_SIZE
- 推荐用于“读多写少”或“批量写入”的 OLTP 场景
🔹 17.9.1.7 SQL Compression Syntax Warnings and Errors(语法警告和错误)
- 常见错误:
- 在系统表空间中启用压缩 → 报错
KEY_BLOCK_SIZE
超出范围 → 报错- 压缩参数不兼容 → 警告
- 如何解读错误信息
- 兼容性说明(不同 MySQL 版本)
⚖️ 五、表压缩的优缺点总结
✅ 优点 | ❌ 缺点 |
---|---|
减少磁盘空间使用 | 增加 CPU 使用率(压缩/解压) |
减少磁盘 I/O | 频繁更新可能导致“压缩失败”或“页分裂” |
更多数据可缓存在 Buffer Pool | 不支持系统表空间 |
索引也被压缩,提升查询性能 | 配置稍复杂(需设置 KEY_BLOCK_SIZE ) |
适合 SSD 存储 | 压缩率取决于数据内容(文本高,二进制低) |
🆚 六、表压缩 vs 页压缩(透明压缩)—— 你应该用哪个?
特性 | 表压缩(Table Compression) | 页压缩(Page Compression) |
---|---|---|
MySQL 版本 | 5.7+ | 8.0.20+ |
启用方式 | ROW_FORMAT=COMPRESSED | COMPRESSION="zstd" |
压缩算法 | zlib | zlib , lz4 , zstd |
性能 | 一般 | 更好(尤其写性能) |
透明性 | 较低 | 高(几乎透明) |
推荐程度 | ❌ 老项目兼容 | ✅ 新项目首选 |
📌 建议:
- 如果你用的是 MySQL 8.0.20+,优先使用 页压缩(透明压缩)
- 如果是老版本或必须用
ROW_FORMAT
,才用表压缩
✅ 总结:关键要点
要点 | 说明 |
---|---|
🔹 表压缩 | 是 InnoDB 的一种页级压缩技术 |
🔹 支持条件 | 必须是 file_per_table 或 通用表空间 |
🔹 启用方式 | ROW_FORMAT=COMPRESSED + KEY_BLOCK_SIZE |
🔹 压缩算法 | zlib |
🔹 监控工具 | INFORMATION_SCHEMA.INNODB_CMP |
🔹 适合场景 | 大表、SSD、读多写少、归档数据 |
🔹 注意事项 | 增加 CPU 开销,不支持系统表空间 |
🔹 新项目建议 | 使用更现代的 页压缩(COMPRESSION) |
💡 一句话建议:
如果你在维护一个老系统,或者必须使用
ROW_FORMAT
,可以使用 InnoDB 表压缩;但如果是新项目,强烈建议直接使用 MySQL 8.0 的 透明页压缩(COMPRESSION="zstd"
),更简单、更高效。
需要我帮你写一个脚本,自动分析哪些表适合启用压缩吗?