InnoDB 将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页大小一般为16KB。
系统变量
innodb_page_size
表明了InnoDB存储引擎中的页大小,默认值为16384字节,该变量只能在第一次初始化MySQL数据目录指定,之后不能修改了。
InnoDB 记录格式
COMPACT,REDUNDANT,DYNAMIC,COMPRESSED
可以在创建表指定使用的行格式
CREATE TABLE demo (
c1 VARCHAR(10),
c2 VARCHAR(10) NOT NULL,
c3 CHAR(10),
c4 VARCHAR(10)
) CHARSET=ascii ROW_FORMAT=COMPACT;
或者修改表的语句中指定使用的行格式
ALTER TABLE 表名 ROW_FORMAT=行格式名称;
COMPACT 格式
先插入2组数据:
SELECT * FROM demo;
+---------+---------+---------+---------+
| c1 c2 c3 c4 |
+---------+---------+---------+---------+
| aaaa bbb cc d |
| eeee fff NULL NULL |
+---------+---------+---------+---------+
-
变长字段长度列表
MySQL 支持一些变长的数据类型,比如VARCHAR,VARBINARY,各种TEXT类型,各种BLOB类型。这些数据列我们称之为变长字段。变长字段中存储多少字节的数据是不固定的,所以我们在存储真实数据的时候需要顺便把这些数据占用的字节数也存储起来。compact 行格式中,将其放在放在 变长字段长度列表中,各变长字段的真实数据占用按照列的顺序逆序存放。
变长字段列为 c1 c2 c4,按照列的顺序逆序存放,所以第一条记录的变长字段长度就是:01 03 04
-
NULL 值列表
一条记录中某些列可能存储NULL值,如果把这些NULL值都放到记录的真实数据中存储会很占地方,COMPACT 行格式把一条记录中值为NULL的列统一管理起来,存储到NULL值列表中,它的处理过程如下:首先统计表中允许存储NULL的列有哪些 ?
主键列以及使用NOT NULL
修饰的列都是不可以存储 NULL 的值,所以在统计时不会把这些列算进去。上面就是c1,c3,c4列。-
如果表中没有允许存储NULL的列,则NULL值列表也就不存在了,否则将每个允许存储NULL的列对应一个二进制位,二进制位为1表示该列的值为NULL,否则表示不为NULL。同时MySQL 规定NULL值列表必须用整数各字节的位表示,如果使用的二进制位个数不是整数个字节,则在字节的高位补0
所以上面的2条记录NULL 值列表如下:
-
记录头信息
记录头信息由固定的 5 字节组成,用于描述记录的一些属性。名称 大小 描述 预留位1 1 没有使用 预留位2 1 没有使用 deleted_flag 1 标记该记录是否被删除 min_re_flag 1 B+树的每层非叶子节点中最小的目录项都会添加该标记 n_owned heap_no record_type next_record -
记录的真实数据
对于表来说,记录的真实数据除了自己定义的外,MySQL还会为每个记录默认添加一些列(也称为隐藏列)。名称 是否必需 占用空间 描述 row_id 否 6字节 行ID,唯一标识一条记录 trx_id 是 6字节 事务ID roll_pointer 是 7字节 回滚指针 - InnoDB 主键生成策略
- 优先使用用户自定义的主键为主键。
- 如果用户没有定义主键,则选取一个不允许存储 NULL 值的 UNIQUE 健作为主键。
- 如果表中连不允许存储 NULL 值的 UNIQUE 健都没有,则InnoDB则会为表默认添加一个
row_id
的隐藏列作为主键。
- InnoDB 主键生成策略
CHAR(M)列的存储格式
对于CHAR(M)类型的列来说,当列采用的是定长编码的字符集时,该列占用的字节数不会被加到变长字段长度列表中,但是如果采用变长编码的字符集时,该列占用的字节数还是会被加到变长字段长度列表。溢出列
REDUNDANT
过时了,这里不分析。
DYNAMIC
DYNAMIC, COMPRESSED和 COMPACT 格式挺像的,只不过在处理溢出列的时候。
COMPRESSED
不同于DYNAMIC,COMPRESSED 行格式会采用压缩算法对页面进行压缩,以节省空间。