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",更简单、更高效。

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

相关推荐
cr7xin20 小时前
基于Session和Redis实现短信验证码登录
数据库·redis·缓存
乌暮20 小时前
数据库--视图、索引
数据库
Web3&Basketball20 小时前
达梦数据库性能调优总结
数据库·oracle
-Xie-20 小时前
Mysql杂志(三十三)——锁
数据库·mysql
情深不寿31720 小时前
MySQL————索引
数据库·mysql
三十_20 小时前
TypeORM 一对一关联篇:掌握实体关系与 JoinColumn
数据库
Brianna Home20 小时前
博客安全攻防演练:从攻击者视角构筑铜墙铁壁
网络·数据库·安全·oracle
冻咸鱼21 小时前
MySQL表设计详解
数据库·mysql·1nf·2nf·3nf
小小测试开发21 小时前
Python SQLAlchemy:告别原生 SQL,用 ORM 优雅操作数据库
数据库·python·sql·sqlalchemy
施嘉伟21 小时前
浅谈信创数据库改造重难点
数据库