推荐链接:
总结——》【Java】
总结——》【Mysql】
总结——》【Redis】
总结——》【Kafka】
总结——》【Spring】
总结——》【SpringBoot】
总结——》【MyBatis、MyBatis-Plus】
总结——》【Linux】
总结——》【MongoDB】
总结——》【Elasticsearch】
Mysql——》InnoDB行格式
- 一、概念
- 二、查看行格式
- 三、指定行格式
- 四、行格式的类型
- 1、COMPACT
- (1)变长字段长度列表
- (2)NULL值列表
- (3)记录头信息
- (4)隐藏列信息
- 2、Redundant
- 3、Dynamic
- 4、Compressed
- 五、不同类型的行格式如何处理行溢出数据
- 1、Compact和Redundant行格式
- 2、Dynamic和Compressed行格式
Q:当我们想从表中获取某些记录时,InnoDB存储引擎需要一条一条的把记录从磁盘读到内存中吗?
A:InnoDB将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小一般为 16 KB。也就是在一般情况下,一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘中。
一、概念
我们平时是以记录为单位来向表中插入数据的,这些记录在磁盘上的存放方式也被称为行格式。
二、查看行格式
-- 查看行格式,默认值为dynamic
show variables like 'innodb_default_row_format';
三、指定行格式
-- 创建表时指定行格式
CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称;
-- 修改表时指定行格式
ALTER TABLE 表名 ROW_FORMAT=行格式名称;
四、行格式的类型
InnoDB存储引擎设计了4种不同类型的行格式:
- Compact
- Redundant
- Dynamic:默认行格式
- Compressed
1、COMPACT
-- 创建表时指定行格式类型为COMPACT
create table test_compact(c1 VARCHAR(10)) ROW_FORMAT=COMPACT;
(1)变长字段长度列表
Q:变长的数据类型?
A:VARCHAR(M)、VARBINARY(M)、TEXT、BLOB
Q:为什么要单独存储变长字段长度列表?
A:变长字段中存储多少字节的数据是不固定的,所以我们在存储真实数据的时候需要顺便把这些数据占用的字节数也存起来。
小于255字节用1个字节存放长度
大于255字节用2个字节存放长度
(2)NULL值列表
Q:为什么要单独存储NULL值列表?
A:如果把NULL值都放到记录的真实数据中存储会很占地方,所以Compact行格式把这些值为NULL的列统一管理起来,存储到NULL值列表。
每个允许存储NULL的列对应一个二进制位:
- 二进制位的值为1时,代表该列的值为NULL
- 二进制位的值为0时,代表该列的值不为NULL
(3)记录头信息
由固定的5个字节(40个二进制位)组成,不同的位代表不同的意思。
记录头 | 二进制位数 | 描述 |
---|---|---|
预留位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 | 表示下一条记录的相对位置 |
(4)隐藏列信息
MySQL会为每个记录默认的添加一些隐藏列
隐式字段 | 是否必须 | 长度(字节) | 作用 | 描述 |
---|---|---|---|---|
DB_ROW_ID | 否 | 6 | 唯一ID | 唯一标识一条记录 随着插入单调递增的行ID 如果有主键或者合适的唯一索引:聚集索引中不包含 DB_ROW_ID 如果没有主键或合适的唯一索引:DB_ROW_ID为主键,自动生成聚集索引 |
DB_TRX_ID | 是 | 6 | 事务ID | 记录最近修改(修改/插入)事务ID |
DB_ROLL_PTR | 是 | 7 | 回滚指针 | 用于配合undo日志,指向这条记录的上一个版本。 每次对某条聚簇索引记录进行改动时,都会把旧的版本写入到undo日志中。 不同事务或者相同事务的对同一记录的修改,会导致该记录的undo log成为一条记录版本线性表,也就是版本链。 |
Q:InnoDB表对主键的生成策略?
A:参考链接:Mysql——》InnoDB主键生成策略
2、Redundant
Redundant行格式是MySQL5.0之前用的一种行格式,不予深究。
3、Dynamic
MySQL5.7的默认行格式就是Dynamic。Dynamic和Compact行格式挺像,只不过在处理行溢出数据时有所不同。
4、Compressed
Compressed行格式和Compact行格式挺像,只不过在处理行溢出数据时有所不同。Compressed行格式会采用压缩算法对页面进行压缩,以节省空间。
五、不同类型的行格式如何处理行溢出数据
MySQL中磁盘和内存交互的基本单位是页,我们的记录都会被分配到某个页中存储。而一个页的大小一般是16KB = 16384字节,而一个VARCHAR(M)类型的列就最多可以存储65532个字节,这样就可能造成一个页存放不了一条记录的情况。
-- 如果往这个字段插入60000个字符,会发生什么?
CREATE TABLE test_varchar( c VARCHAR(60000) )
1、Compact和Redundant行格式
对于占用存储空间非常大的列,在记录的真实数据处只会存储该列的前768个字节的数据,然后把剩余的数据分散存储在几个其他的页中,记录的真实数据处用20个字节存储指向这些页的地址。这个过程也叫做行溢出,存储超出768字节的那些页面也被称为溢出页。
2、Dynamic和Compressed行格式
不会在记录的真实数据处存储字段真实数据的前768个字节,而是把所有的字节都存储到其他页面中,只在记录的真实数据处存储其他页面的地址。