MySQL小册子笔记 5 InnoDB 记录存储结构
-
InnoDB 是 MySQL 默认的存储引擎
-
读写磁盘的速度非常慢,和内存读写差了几个数量级
将数据划分为若干个页,以页
作为磁盘和内存之间交互的基本单位
,InnoDB中页的大小一般为 16 KB
。
也就是在一般情况下,一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘中。
- 我们平时是以
记录
为单位来向表中插入数据的,这些记录在磁盘上的存放方式也被称为行格式
或者记录格式
。
4种常用的行格式是 Compact
、Redundant
、Dynamic
和 Compressed
行格式。
- 指定行格式
CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称;
ALTER TABLE 表名 ROW_FORMAT=行格式名称;
CREATE TABLE record_format_demo (
c1 VARCHAR(10),
c2 VARCHAR(10) NOT NULL,
c3 CHAR(10),
c4 VARCHAR(10)
) CHARSET=ascii ROW_FORMAT=COMPACT;
INSERT INTO record_format_demo(c1, c2, c3, c4) VALUES('aaaa', 'bbb', 'cc', 'morningcat2018'), ('eeee', 'fff', NULL, NULL);
+------+-----+------+---------------------+
| c1 | c2 | c3 | c4 |
+------+-----+------+---------------------+
| aaaa | bbb | cc | morningcat2018 |
| eeee | fff | NULL | NULL |
+------+-----+------+---------------------+
- Compact 行格式
- 记录的额外信息
- 变长字段长度列表
- MySQL支持一些变长的数据类型,比如VARCHAR(M)、VARBINARY(M)、各种TEXT类型,各种BLOB类型;这些数据类型的列称为
变长字段
- 这些变长字段占用的存储空间分为两部分:1 真正的数据内容 ,2 占用的字节数
- 各变长字段数据占用的字节数按照列的顺序
逆序存放
- 第一条记录中 c1、c2、c4 列都是变长字段,长度分别为 4,2,14 ;所以
变长字段长度列表
的值为0E0204
(十六进制表示) - 第二条记录中 c4为NULL 不进行记录;所以
变长字段长度列表
的值为0304
- 第一条记录中 c1、c2、c4 列都是变长字段,长度分别为 4,2,14 ;所以
- MySQL支持一些变长的数据类型,比如VARCHAR(M)、VARBINARY(M)、各种TEXT类型,各种BLOB类型;这些数据类型的列称为
- NULL值列表
- 使用 1bit 存储,1 代表该列的值为NULL;0 代表该列的值不为NULL
- 逆序存放
- 高位补零
- 只有可能为NULL的列才会存储在此;所以 record_format_demo 表的
NULL值列表
为 0000 0 c4 c3 c1- 第二条记录中,c3 c4为NULL,值为1 ;所以
NULL值列表
为 0000 0110 ;十六进制表示为06
- 第二条记录中,c3 c4为NULL,值为1 ;所以
- 记录头信息
- 固定的
5个字节
组成(40 bit)- 预留位1 1bit
- 预留位2 1bit
- delete_mask 1bit 标记该记录是否被删除
- min_rec_mask 1bit B+树的每层非叶子节点中的最小记录都会添加该标记
- n_owned 4bit 表示当前记录拥有的记录数
- heap_no 13bit 表示当前记录在记录堆的位置信息
- record_type 3bit 表示当前记录的类型,0表示普通记录,1表示B+树非叶子节点记录,2表示最小记录,3表示最大记录
- next_record 16bit 表示下一条记录的相对位置
- 固定的
- 变长字段长度列表
- 记录的真实数据
- 除了自定义的列的数据以外,MySQL会为每个记录默认的添加一些列(也称为
隐藏列
)- DB_ROW_ID 非必须 6byte 行ID,唯一标识一条记录
- DB_TRX_ID 必须 6byte 事务ID
- DB_ROLL_PTR 必须 7byte 回滚指针
- InnoDB表对主键的生成策略
- 优先使用用户自定义主键作为主键
- 没有定义主键,则选取一个Unique键作为主键
- 连Unique键都没有定义的话,则InnoDB会为表默认添加一个名为row_id的隐藏列作为主键
- 第1条记录中
- c3列的值,它是CHAR(10)类型的,它实际存储的字符串是:‘cc’,而ascii字符集中的字节表示是’0x6363’,虽然表示这个字符串只占用了2个字节,但整个c3列仍然占用了10个字节的空间,
- 除真实数据以外的8个字节的统统都用空格字符填充,空格字符在ascii字符集的表示就是0x20
- 除了自定义的列的数据以外,MySQL会为每个记录默认的添加一些列(也称为
- Redundant 行格式
Redundant 行格式是 MySQL5.0 之前用的一种行格式
- 行溢出
一个页一般是16KB,当记录中的数据太多,当前页放不下的时候,会把多余的数据存储到其他页中,这种现象称为行溢出