InnoDB 支持哪些文件格式和行记录格式?
在 MySQL 中,InnoDB 存储引擎的数据存储结构分为不同的层级。文件格式(File Format)决定了表空间级别的数据组织方式,而行记录格式(Row Format)决定了单行数据在数据页(Page)中的物理存储方式。
以下是 InnoDB 支持的文件格式和行记录格式的详细说明:
一、 InnoDB 文件格式(File Formats)
InnoDB 历史上主要支持两种文件格式。需要注意的是,在 MySQL 8.0 中,文件格式的概念已被废弃(因为默认且仅支持较新的格式),但在 MySQL 5.7 及之前版本中非常重要。
1. Antelope(羚羊)
- 简介:这是 InnoDB 最原始、最古老的文件格式。
- 支持的行格式:仅支持
REDUNDANT和COMPACT两种行记录格式。 - 限制:不支持表压缩,对包含大字段(BLOB、TEXT)的表处理效率相对较低。
2. Barracuda(梭鱼)
- 简介:在 MySQL 5.1 引入的新文件格式(当时作为插件),是 MySQL 5.7 的默认文件格式。
- 支持的行格式:支持所有的行格式,包括
REDUNDANT、COMPACT,以及新增的DYNAMIC和COMPRESSED。 - 优势:支持数据压缩,并且通过新的行格式优化了对大字段(行溢出)的存储。
(注:MySQL 8.0 移除了 innodb_file_format 参数,默认隐式使用 Barracuda 格式的设计理念。)
二、 InnoDB 行记录格式(Row Formats)
InnoDB 一共支持 4 种行记录格式。现代 MySQL 版本(5.7 和 8.0)默认使用的是 DYNAMIC 格式。
1. REDUNDANT(冗余格式)
- 历史:MySQL 5.0 之前的默认格式,现在极少使用,主要是为了兼容旧版本。
- 特点:顾名思义,存储比较冗余。它会为每个字段保留长度信息,即使是 NULL 值也会占用空间(对于固定长度的类型)。
- 缺点:占用磁盘空间大,导致内存(Buffer Pool)命中率下降,整体性能较差。
2. COMPACT(紧凑格式)
- 历史:MySQL 5.0 引入,MySQL 5.1 ~ 5.6 的默认格式。
- 特点:相比 REDUNDANT 大幅减少了存储空间(约减少 20%)。它引入了变长字段长度列表和NULL值列表,NULL 值不再占用物理存储空间。
- 行溢出处理(关键点):如果某一行的数据特别大(比如包含了长 VARCHAR、TEXT 或 BLOB),一个 16KB 的数据页放不下时,COMPACT 会将该字段的前 768 个字节存放在当前 B+ 树的叶子节点(数据页)中,剩余的数据存放在专门的“溢出页(Overflow Page)”中,并用一个 20 字节的指针指向这些溢出页。
3. DYNAMIC(动态格式)
- 历史:随 Barracuda 文件格式引入,MySQL 5.7 及 8.0 的默认行格式。
- 特点:在数据结构上与 COMPACT 基本一致,主要的区别在于对行溢出(大字段)的处理。
- 行溢出处理(改进点):当发生行溢出时,DYNAMIC 格式不会在 B+ 树叶子节点中保留 768 个字节。它将大字段的所有数据都存放到溢出页中,而在 B+ 树叶子节点中只保留一个 20 字节的指针。
- 优势:这使得 B+ 树的每个节点能存放更多的行,降低了 B+ 树的高度,提高了索引查询的效率。
4. COMPRESSED(压缩格式)
- 历史:同样随 Barracuda 文件格式引入。
- 特点:物理存储方式和 DYNAMIC 类似(大字段全部放在溢出页),但它会在物理存储前,使用 zlib 算法对数据页和索引页进行压缩。
- 使用场景:适用于磁盘空间紧张,或者 I/O 成为瓶颈、但 CPU 资源较为空闲的场景。因为解压缩需要消耗额外的 CPU 资源。
三、 总结与相关命令
| 行记录格式 | 支持的文件格式 | MySQL默认版本 | 处理大字段(行溢出)的方式 | 特点 |
|---|---|---|---|---|
| REDUNDANT | Antelope, Barracuda | 5.0之前 | 存768字节,其余指针 | 废弃,空间占用大 |
| COMPACT | Antelope, Barracuda | 5.1 ~ 5.6 | 存768字节,其余指针 | 紧凑设计,节省空间 |
| DYNAMIC | Barracuda | 5.7, 8.0 | 仅存20字节指针,数据全在溢出页 | 当前主流,B+树效率高 |
| COMPRESSED | Barracuda | 无 | 同 DYNAMIC | 节约磁盘,消耗 CPU |
如何查看和设置?
查看默认的行格式:
sqlSHOW VARIABLES LIKE 'innodb_default_row_format';查看某张表的行格式:
sqlSHOW TABLE STATUS LIKE '你的表名'\G -- 或者查看 information_schema SELECT NAME, ROW_FORMAT FROM information_schema.innodb_tables WHERE NAME = '数据库名/表名';创建表时指定行格式:
sqlCREATE TABLE my_table ( id INT PRIMARY KEY, content TEXT ) ROW_FORMAT=DYNAMIC;修改已有表的行格式:
sqlALTER TABLE my_table ROW_FORMAT=COMPRESSED;