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️⃣ 创建表时启用

sql 复制代码
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️⃣ 修改已有表

sql 复制代码
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_CMPINNODB_CMP_PER_INDEX
    • 压缩尝试次数
    • 成功次数
    • 压缩失败原因
    • 平均压缩比

📌 示例查询:

sql 复制代码
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",更简单、更高效。

需要我帮你写一个脚本,自动分析哪些表适合启用压缩吗?

相关推荐
满昕欢喜2 小时前
SQL Server从入门到项目实践(超值版)读书笔记 27
数据库·sql·sqlserver
间彧2 小时前
ProxySQL详解与实战应用
数据库
间彧2 小时前
在MySQL 8.0+版本中,如果MyISAM被弃用,有哪些替代方案可以实现类似读写分离的性能优化?
数据库
code123132 小时前
redis升级方法
数据库·redis·缓存
间彧2 小时前
在读写分离架构中,如何合理搭配使用InnoDB和MyISAM引擎?
数据库
间彧2 小时前
InnoDB的MVCC机制是如何实现并发控制的?
数据库
间彧2 小时前
MySQL中InnoDB和MyISAM引擎的主要区别是什么?
数据库
清静诗意3 小时前
Django as_view 方法中的闭包设计解析
数据库·django
苹果醋33 小时前
SpringCloud高可用集群搭建及负载均衡配置实战
java·运维·spring boot·mysql·nginx