InnoDB行记录格式
InnoDB存储引擎和大多数数据库一样,记录是以行的形式存储的。
这意味着页总保存着表中一行行的数据。
InnoDB存储引擎提供了Compact和Redundant两种格式来存放行记录数据。
Redundant格式是为兼容之前版本而保留的,Compact是MySQL 5.1版本默认的行格式。
可以通过命令 SHOW TABLE STATUS LIKE "table_name" 来查看那当前表使用的行格式。
Compact行记录格式
Compact行记录是在MySQL 5.0中引入的,其设计目标是高效地存储数据。简单来说,
一个页中存放的行数据越多,其性能就越高。
| 变长字段长度列表 | NULL标志位 | 记录头信息 | 列1数据 | 类2数据 | ... |
Compact行记录格式的首部是一个非NULL变长字段长度列表,并且其是按照列的顺序逆序放置的,
长度为:
- 若列的长度小于255字节,用1字节表示
- 若大于255个字节,用2字节表示(所以
VARCHAR类型最大长度是65535)
第二部分是NULL标识位,指示了该行数据中是否有NULL值,有则用1表示。
第三部分是记录头信息(record header),固定占用5字节。含义如下:
| 名称 | 大小(bit) | 描述 |
|---|---|---|
| () | 1 | 未知 |
| () | 1 | 未知 |
| deleted_flag | 1 | 该行是否已被删除 |
| min_rec_flag | 1 | 为1,如果该记录是预先被定义为最小的记录 啥子? |
| n_owned | 4 | 该记录拥有的记录数 |
| heap_no | 13 | 索引堆中该记录的排序记录 |
| record_type | 3 | 记录类型,000表示普通,001表示B+树节点指针,010表示Infimun 011表示Supremum,1xx表示保留 |
| next_record | 16 | 页中下一条记录的相对位置 |
| total | 40 |
最后部分就是实际存储每个列的数据。需要特别注意的是,NULL不占该部分任何空间。
此外,每行数据除了用户定义的列外,还有两个隐藏列,事务ID列和回滚指针列,
分别为6字节和7字节的大小。若
InnoDB表没有定义主键,每行还会增加一个6字节的rowid列。
Redundant行记录格式
Redundant 是MySQL 5.0版本之前InnoDB的行记录存储方式。
| 字段长度偏移列表 | 记录头信息 | 列1数据 | 列2数据 | ... |
行溢出数据
InnoDB存储引擎可以将一条记录的某些数据存储在真正的数据页面之外。
一般认为BLOB、LOB这类的大对象列类型的存储会把数据存放在数据页面之外。
VARCHAR列数据类型也有可能存放为行溢出数据。
InnoDB存储引擎并不支持65535长度的VARCHAR。这是因为还有别的开销,
实际测试发现能存放的最大长度为65532。
InnoDB存储引擎的页为16KB,即16384字节,怎么存储65532字节?
在一般情况下,InnoDB存储引擎的数据都是存放在页类型为B-tree node中,
但当发生行溢出时,数据存放在页类型为Uncompress BOLB页中。
啊,这书里写的,我没试过
MySQL官方手册中定义的65535长度是指所有VARCHAR列的长度总和。
Compressed和Dynamic行记录格式
InnoDB 1.0.x版本开始引入了新的文件格式,以前支持的Compact和Redundant格式
称为Antelope文件格式,新的文件格式称为Barracuda文件格式。
Barracuda文件格式拥有两种新的行记录格式:Compressed和Dynamic。
新的两种记录格式对于存放在BLOB中的数据采用了完全的行溢出的方式,在数据页中
值存放20个字节的指针,实际数据存放在Off Page中,而之前的Compact和Redundant
两种格式会存放768个前缀字节。
Compressed行记录格式的另一个功能就是,存储在其中的行数据会以zlib的算法进行压缩,
因此对于BLOB、TEXT、VARCHAR这类大长度类型的数据能够进行非常有效的存储。
CHAR的行结构存储
从MySQL 4.1版本开始,CHR(N)中的N指的是字符的长度,而不是之前版本的字节长度。
也就是在不同的字符集下,CHAR类型列内部存储的可能不是定长的数据。