4_InnoDB的记录结构
MySQL服务器中存储引擎负责对表中数据的读取和写入。
为支持不同的特性,MySQL提供了不同类型的存储引擎,其中存放数据的格式各不相同。
专注于最常用的InnoDB存储引擎。
InnoDB页简介
InnoDB将表中的数据存储到磁盘(断电不丢失),处理数据发生在内存。
读取需要把磁盘中的数据加载到内存中,写入/修改需要把内存中的内容刷新到磁盘上。
磁盘读写的速度比内存读写慢了几个数量级,一次操作通常涉及多条记录,若磁盘与内存交互时每条记录都需要访问磁盘,则会执行太慢。
InnoDB中以页作为磁盘和内存之间交互的基本单位,页的大小一般为16KB。
InnoDB行格式
记录在磁盘上的存放方式也被称为行格式。
InnoDB存储引擎有4种不同类型的行格式。
- Compact;
- Redundant;
- Dynamic;
- 默认行格式;
- 行溢出时,只记录存储其他页面的地址,所有的字节都会存储到其他页面中;
- Compressed;
- 采用压缩算法对页面进行压缩;
指定行格式
CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称
;ALTER TABLE 表名 ROW_FORMAT=行格式名称
;
Compact
-
记录的额外信息
-
变长字段长度列表
- 可以存储不固定字节数的的列称为变长字段;
- 变长类型VARCHAR(M)、VARBINARY(M)、TEXT、BLOB;
- 定长类型 + 变长字符集(GBK、UTF8等);
- 存储数据占用的字节数;
- 各变长字段长度数按照列的顺序逆序存放,形成变长字段长度列表;
- 细节
- 如果该可变字段允许存储的最大字节数(M×W)超过255字节并且真实存储的字节数(L)超过127字节,则使用2个字节,否则使用1个字节,其中M为字符集的Maxlen,W为字符数;
- 变长字段长度列表中只存储值为非NULL的列内容占用的长度,不存储值为NULL的列的长度;
- 非变长的数据类型列不需要存储列长;
- 可以存储不固定字节数的的列称为变长字段;
-
NULL值列表
- 列存储NULL值,为节省空间,不会存储真实数据NULL值,而是在额外信息的NULL值列表统一标识;
- 处理过程
- 统计表中允许存储NULL的列;
- 主键列、被NOT NULL修饰的列不可以存储NULL值;
- 默认列可以存储NULL值;
- 若不存在允许存储 NULL 的列,则NULL值列表也不存在;
- 将每个允许存储NULL的列对应一个二进制位,二进制位按照列的顺序逆序排列
- 二进制位为0,代表列的值不为NULL;
- 二进制位为1,代表列的值为NULL;
- 二进制位用整数个字节表示,不满足则在字节的高位补0;
- 统计表中允许存储NULL的列;
-
记录头信息
-
由固定的40个二进制位(5个字节)组成。
-
名称 大小(单位:bit) 描述 预留位1
1
没有使用 预留位2
1
没有使用 delete_mask
1
标记该记录是否被删除 min_rec_mask
1
B+树的每层非叶子节点中的最小记录都会添加该标记 n_owned
4
表示当前记录拥有的记录数 heap_no
13
表示当前记录在记录堆的位置信息 record_type
3
表示当前记录的类型, 0
表示普通记录,1
表示B+树非叶子节点记录,2
表示最小记录,3
表示最大记录next_record
16
表示下一条记录的相对位置
-
-
-
记录的真实数据
-
隐藏列
-
简写列名 真正名称 是否必须 占用空间 描述 row_id
DB_ROW_ID 否 6
字节行ID,唯一标识一条记录 transaction_id
DB_TRX_ID 是 6
字节事务ID roll_pointer
DB_ROLL_PTR 是 7
字节回滚指针 -
InnoDB主键的生成策略:用户自定义主键 > Unique键 > row_id
-
在没有自定义主键以及Unique键时,才会添加row_id
-
-
用户数据
- 定长字段,填充0值;
- 变长字段,不存储;
-
行溢出数据
VARCHAR最大字符数
除BLOB或者TEXT类型的列之外,其他所有的列(不包括隐藏列和记录头信息)占用的字节长度加起来不能超过65535个字节。
- 用户数据;
- 变长字段长度列表;
- NULL值列表;
计算VARCHAR(M)最大字符数
- 变长字段长度占2个字节;
- NULL标识需要1个字节,NOT NULL则无需占用;
- ASCII字符集中1个字符占1个字节;
- 最大字符数为(65535 - 2 - 0) / 1 = 65533;
- 若为utf8字符集,则最大字符数为(65535 - 2 - 0) / 3 = 21844;
记录中数据太多产生的溢出
- 一页大小为16384B < VARCHAR(M)类型的最大占用存储65532B,存在一页无法存放一条记录的情况;
- 行溢出
- 在本记录的真实数据处只会存储该列的前768个字节的数据和指向其他页的地址;
- 把存储超出768字节的数据存放到其他页中,这些页面也被称为溢出页;
- 行溢出的临界点
- 当单行单列,一页2条数据时,数据字节数n > 8098;
- 如果在一个行中存储了很大的数据,可能会发生行溢出,注意宽表;