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
类型列内部存储的可能不是定长的数据。