MySQL压缩表创建指南
这段内容是 MySQL 官方文档 17.9.1.2 节:创建压缩表(Creating Compressed Tables),它详细说明了如何在两种不同类型的表空间中创建 InnoDB 压缩表,并解释了相关的语法、限制和注意事项。
我们来一步步拆解、翻译并通俗化讲解,让你彻底理解:
✅ 如何正确创建一个压缩表
⚠️ 需要注意哪些坑
🔧 各参数的含义与关系
🎯 一句话总结
你可以通过
ROW_FORMAT=COMPRESSED
和KEY_BLOCK_SIZE
在 独立表空间(file-per-table) 或 通用表空间(general tablespace) 中创建压缩表,但 不能在系统表空间中使用压缩。两者配置方式略有不同,尤其是通用表空间需要预先定义FILE_BLOCK_SIZE
。
📁 一、支持压缩的表空间类型回顾
表空间类型 | 是否支持压缩 | 说明 |
---|---|---|
✅ 文件独立表空间(.ibd 文件) | 是 | 每个表一个文件,默认开启 |
✅ 通用表空间(General Tablespace) | 是 | 多个表共享一个 .ibd 文件 |
❌ 系统表空间(ibdata1 ) | 否 | 包含系统数据(如 undo log),不支持压缩 |
📌 所以:只要你的表不是放在 ibdata1
里,就可以压缩。
🛠️ 二、方法一:在“独立表空间”中创建压缩表
✅ 前提条件:
innodb_file_per_table=ON
(默认就是 ON)
SET GLOBAL innodb_file_per_table = 1; -- 可选:确保启用(通常已默认)
✅ 创建语句:
CREATE TABLE t1 (c1 INT PRIMARY KEY
)
ROW_FORMAT = COMPRESSED
KEY_BLOCK_SIZE = 8;
🔍 参数说明:
参数 | 作用 |
---|---|
ROW_FORMAT=COMPRESSED | 明确启用压缩 |
KEY_BLOCK_SIZE=8 | 目标压缩页大小为 8KB(单位是 KB) |
💡 实际磁盘上的页会被压缩到接近这个大小(如原始 16KB → 压缩成 ~8KB)
🧱 三、方法二:在“通用表空间”中创建压缩表
这是重点,比独立表空间复杂一些。
✅ 步骤 1:先创建通用表空间,指定 FILE_BLOCK_SIZE
CREATE TABLESPACE `ts2`
ADD DATAFILE 'ts2.ibd'
FILE_BLOCK_SIZE = 8192
ENGINE=InnoDB;
FILE_BLOCK_SIZE = 8192
:表示这个表空间的 物理块大小是 8KB- 单位是 字节(注意!和
KEY_BLOCK_SIZE
不同)
✅ 步骤 2:创建表时,KEY_BLOCK_SIZE
必须匹配
CREATE TABLE t4 (c1 INT PRIMARY KEY
)
TABLESPACE ts2
ROW_FORMAT = COMPRESSED
KEY_BLOCK_SIZE = 8; -- 8192 字节 = 8KB
🔗 关键规则:
KEY_BLOCK_SIZE
(单位 KB)必须等于FILE_BLOCK_SIZE / 1024
innodb_page_size | FILE_BLOCK_SIZE | KEY_BLOCK_SIZE |
---|---|---|
16384 (16KB) | 8192 (8KB) | 8 |
16384 | 4096 | 4 |
16384 | 2048 | 2 |
❌ 如果不匹配?→ 报错!
📝 四、重要注意事项(Notes)
1️⃣ MySQL 8.0 起:压缩表空间文件更小
“The tablespace file for a compressed table is created using the physical page size…”
- 以前:空压缩表也占满 16KB 一页
- 现在:直接按压缩后的大小分配空间 → 初始
.ibd
文件更小
✅ 好处:节省空间,启动更快
2️⃣ ROW_FORMAT=COMPRESSED
和 KEY_BLOCK_SIZE
可以互相推导
你写的 | 实际效果 |
---|---|
ROW_FORMAT=COMPRESSED (无 KEY_BLOCK_SIZE ) | 自动设为 innodb_page_size / 2 → 通常是 8KB |
KEY_BLOCK_SIZE=4 (无 ROW_FORMAT ) | 自动启用压缩 |
📌 所以这两个参数写一个就行,另一个可省略。
3️⃣ 如何选择最佳 KEY_BLOCK_SIZE
?
文档建议:
“typically you create several copies of the same table with different values… then measure performance”
✅ 推荐做法:
- 创建多个副本:
KEY_BLOCK_SIZE=8
,4
,2
- 导入真实数据
- 测量:
.ibd
文件大小- 查询性能(TPS/QPS)
- CPU 使用率
- 选择综合最优值
📌 经验值:
- 大多数场景用
8
就很好 - 数据特别大或 SSD 成本敏感 → 尝试
4
或2
4️⃣ KEY_BLOCK_SIZE
是“提示”,不是强制
- InnoDB 可能根据实际情况调整
- 如果设得太大(>
innodb_page_size
)→ 忽略,警告,自动改为一半 - 如果
innodb_strict_mode=ON
(默认)→ 直接报错
5️⃣ 大页(32KB/64KB)不支持压缩!
“InnoDB supports 32KB and 64KB page sizes but these do not support compression.”
innodb_page_size=32768
或65536
→ 无法使用压缩- 所以想用压缩,必须保持
innodb_page_size ≤ 16KB
6️⃣ 设置 KEY_BLOCK_SIZE = 16
有意义吗?
-
对于独立表空间:
KEY_BLOCK_SIZE=16
→ 通常压缩率很低(因为原始页就是 16KB)- 但对 包含大量 BLOB/TEXT 的表 仍可能有效,因为这些字段会存到“溢出页”(off-page),压缩后可减少溢出页数量
-
对于通用表空间:
- ❌ 不允许
KEY_BLOCK_SIZE = innodb_page_size
- 必须小于原始页大小
- ❌ 不允许
7️⃣ 所有索引都会被压缩
“All indexes of a table… are compressed using the same page size”
- 主键(聚簇索引)、二级索引、唯一索引 → 全部压缩
- 压缩是 整表级别 的,不是按行或按索引设置
CREATE INDEX
时不支持指定压缩参数(会被忽略)
🚫 五、压缩表的限制(Restrictions)
限制 | 说明 |
---|---|
❌ 不能在系统表空间中压缩 | ibdata1 不支持 |
❌ 通用表空间内不能混用压缩和非压缩表 | 要么全压缩,要么全不压缩 |
❌ 不支持压缩临时表 | CREATE TEMPORARY TABLE ... COMPRESSED → 报错或自动转为非压缩 |
❌ 压缩是整表行为 | 不能只压缩某几列或某几个索引 |
❌ CREATE INDEX 不支持压缩语法 | 但继承表的压缩设置 |
🧩 六、参数对比表(关键区别)
参数 | 出现场景 | 单位 | 示例 | 说明 |
---|---|---|---|---|
innodb_page_size | 全局配置 | 字节 | 16384 | 内存中的原始页大小(默认 16KB) |
KEY_BLOCK_SIZE | CREATE TABLE | KB | 8 | 目标压缩页大小(KB) |
FILE_BLOCK_SIZE | CREATE TABLESPACE | 字节 | 8192 | 通用表空间的物理块大小 |
📌 记住:KEY_BLOCK_SIZE = FILE_BLOCK_SIZE / 1024
✅ 七、完整示例:推荐做法
场景:在通用表空间中创建压缩表
-- 1. 创建通用表空间(8KB 物理块)
CREATE TABLESPACE `compressed_ts`
ADD DATAFILE 'compressed_ts.ibd'
FILE_BLOCK_SIZE = 8192
ENGINE=InnoDB;-- 2. 创建压缩表(KEY_BLOCK_SIZE=8)
CREATE TABLE sales_archive (id BIGINT AUTO_INCREMENT PRIMARY KEY,product VARCHAR(100),amount DECIMAL(10,2),created_date DATE
) TABLESPACE compressed_ts KEY_BLOCK_SIZE = 8; -- ROW_FORMAT=COMPRESSED 自动启用
✅ 总结:关键要点
要点 | 说明 |
---|---|
✅ 支持压缩的表空间 | file-per-table 和 general tablespace |
❌ 不支持 | 系统表空间、临时表 |
🔧 启用方式 | ROW_FORMAT=COMPRESSED 或 KEY_BLOCK_SIZE=N |
📏 KEY_BLOCK_SIZE | 目标压缩页大小(KB),常用 8/4/2 |
🧱 通用表空间 | 必须先设 FILE_BLOCK_SIZE (字节),且 KEY_BLOCK_SIZE = FILE_BLOCK_SIZE/1024 |
🔄 参数互推 | 写一个,另一个可自动推导 |
📊 最佳实践 | 测试不同 KEY_BLOCK_SIZE ,选择最优 |
⚠️ 注意 | 大页(32KB/64KB)不支持压缩 |
💡 一句话建议:
如果你是普通用户,直接用 独立表空间 +
KEY_BLOCK_SIZE=8
就够了;如果是 DBA 管理多个大表,可以考虑 通用表空间 + 统一压缩策略,但要严格遵守FILE_BLOCK_SIZE
和KEY_BLOCK_SIZE
的匹配规则。
需要我帮你写一个脚本来批量分析哪些表适合压缩吗?