Innodb行格式

发布时间 2023-07-01 19:51:17作者: WYFC4

InnoDB行格式

InnoDB是一个将表中的数据存储到磁盘上的存储引擎。 为了方便磁盘与内存的读取,InnoDB以页的格式存储数据。我们可以通过 SHOW GLOBAL VARIABLES LIKE 'innodb_page_size'; 的方式查看页的大小。 一般来说,页的大小会设置为16384(16KB)。

我们以记录为单位向表中插入数据。 这些记录在磁盘存储的格式称为行格式或者纪录格式。 我们可以通过下面的方式指定或者修改表的行格式:

CREATE TABLE (TABLE NAME) (COLUMN INFORMATION) ROW_FORMAT=();
ALTER TABLE (TABLE NAME) ROW_FORMAT=();

行格式主要有四类:

  • COMPACT
  • REDUNDANT
  • DYNAMIC
  • COMPRESSED

COMPACT行格式

我们主要以COMPACT为例讲解。COMPACT行格式记录的信息包括记录的额外信息和记录的真实数据两部分,可以表示为

变长字段长度列表,NULL值列表,记录头信息 (额外信息)
列1的信息,列2的信息,……,列n的信息 (真实数据)

记录的额外信息

变长字段长度列表

顾名思义,这块主要以列表形式存储诸如VARCHAR(M), VARBINARY(M) ,各种TEXT类型,各种BLOB类型这样的变长数据类型数据的字节数。各变长字段的真实数据占用的字节数按照列的顺序逆序存放

那么如何确定表的最大长度呢?第一步一定是首先查看表结构,并确定某个变长字段运行存储的最大字节数。 之后比较理论最大字节数(即最多存储的字符数 × 字符集单字符最多需要的字节数)与允许的最大字节数进行比较。 如果超过且真实数据占用的字节超过允许最大字节数\2,那么用2字节表示真实数据占用的字节数。否则使用1字节。

注意:变长字段长度列表中只存储值为非NULL的列的内容长度。 同时,行格式里不是一定要有变长字段长度列表。 比如表中没有变长数据类型或者有但都为NULL,则不需要该列表。

NULL值列表

COMPACT行格式会把表中值为NULL的列统一管理,其过程如下:

1、 统计表中允许存储NULL的列。比如主键列以及用NOT NULL修饰的列是不允许存储NULL值的。 如果表中没有允许存储NULL的列,那么NULL值表就不存在了。
2、 对允许存储NULL值的列对应一个二进制位。 同样, 二进制位按照列的顺序逆序排序。二进制位的意义位:

  • 二进制位为1时, 代表该列的值为NULL
  • 二进制位为0时, 代表该列的值不为NULL

3、 NULL值列表必须以整数字节表示,如果非整需要采用高位补零。

记录头信息

记录头信息有5个字节(40个二进制位),用于描述记录的一些属性。

记录的真实数据

除了表中的原始数据, MySQL还会位某些表默认添加一些列,也就是所谓隐藏列。

列名 是否必需 占用空间 描述
DB_ROW_ID 6字节 行ID, 唯一标识一条记录
DB_TRX_ID 6字节 事务ID
DB_ROLL_PTR 7字节 回滚指针

DB_ROW_ID是针对如果用户没有指定主键列且也没有非NULL列(没有主键MySQL会选取一个不允许存储NULL的列作为主键)的情况下,MySQL会自动生成一个DB_ROW_ID列作为主键列。

REDUNDANT行格式

REDUNDANT行格式同样有两部分:

字段长度偏移列表, 记录头信息(额外信息)
列1的信息,列2的信息,……,列n的信息 (真实数据)

字段长度偏移列表

与变长字段长度列表相比:

  • 所有列(包括隐藏列)的长度信息读按照逆序存储到字段长度偏移列表
  • 采用两个相邻偏移量的差值来计算各个列值的长度

NULL值的处理

列对应的偏移量值的第一个比特位会标记该列是否位NULL,该比特位称为NULL比特位。

溢出列

页的大小一般是16KB,如果出现所需存取的数比页大小大的情况,就会出现所谓“溢出列”的现象。一般MySQL为了解决该问题,会把数据分散存在不同的页中。在行格式的真实数据处会用20字节存储指向这些页的地址。 MySQL规定一个页中至少存放两行记录。