欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 艺术 > 【MySQL篇】行格式详解

【MySQL篇】行格式详解

2025/2/11 0:15:04 来源:https://blog.csdn.net/m0_53732433/article/details/145534404  浏览:    关键词:【MySQL篇】行格式详解

MySQL行格式详解

文章目录

  • MySQL行格式详解
    • 🎉 什么是行格式
    • 🐱‍👤 如何查看行格式
    • 🐱‍🚀 InnoDB 行格式有哪些?
    • 🐱‍🏍 Compact 行格式
      • 🚩 额外信息
        • 🚀 变长字段长度列表
        • 🚓 Null值列表
        • 🚁 记录头
      • 🌌 真实数据
        • 🌍 隐藏字段
        • 🗻 存储的真正字段

🎉 什么是行格式

首先我们得明确一点,行格式是存在页中的,数据页中存储的行格式是数据行(也就是实际数据),目录页存的是目录项记录【非叶子节点行】(存储页号和主键)

🐱‍👤 如何查看行格式

-- 创建数据表时,显示指定行格式
CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称;-- 创建数据表时,修改行格式
ALTER TABLE 表名 ROW_FORMAT=行格式名称;-- 查询数据表信息
show table status from 数据库名 like '<数据表名>';
-- 指定行格式
create table task2
(idx int auto_increment,primary key (idx)
) row_format = compact;-- 查看行格式
show table status from test1 like 'task2';

可以看到下图 Row_format 字段种就是行格式

在这里插入图片描述

🐱‍🚀 InnoDB 行格式有哪些?

InnoDB提供了四种行格式,分别是RedundantCompactDynamic Compressed

特性/格式RedundantCompactDynamicCompressed
存储效率最低,存在冗余中等,行头较小,适合常规数据高效,特别是对于大字段的存储极高,适用于大规模压缩,节省磁盘空间
适合场景旧版本兼容,较小数据表默认格式,常规数据库适合大字段存储和需要高压缩的场景大量数据表,磁盘空间有限,压缩需求高
行头大小较大,包含多余的标记和指针较小,更紧凑的存储结构较大,包含更多字段指针和溢出页信息行头较大,压缩后存储空间利用较高
大字段存储存储在行内或溢出页存储在行内或溢出页存储在外部溢出页,仅保存指针存储在溢出页,且经过压缩处理
压缩支持不支持压缩不支持压缩不支持压缩支持压缩,数据写入时自动压缩
性能较低,冗余存储带来性能损失性能平衡,适合一般负载性能较好,适合大字段,处理复杂数据表性能较低,解压缩开销较大
兼容性主要用于早期 MySQL 版本MySQL 5.0 之后推荐的默认行格式MySQL 5.0 之后推荐的格式用于对存储空间要求高的数据库
  • Redundant:不再推荐使用,主要用于与早期版本的兼容。
  • Compact:适用于常规数据存储,提供较好的性能和存储效率,是大多数情况下的默认行格式。
  • Dynamic:适合大字段、可变长度字段,特别是存储 TEXTBLOB 等类型的数据,能够有效提高存储效率。
  • Compressed:适用于对存储空间有较高需求,尤其是存储大量数据时,能够显著减少磁盘使用,但可能会引入 CPU 开销。

下面我们主要介绍一下 Compact 行格式

🐱‍🏍 Compact 行格式

如下图是 Compact 行格式的一个图解

在这里插入图片描述

Compact 行格式主要分为几个部分

🚩 额外信息

🚀 变长字段长度列表

变长字段长度列表主要是记录变长字段 varchar 所占的长度大小,举个例子,有如下表

CREATE TABLE `t_user` (`id` int(11) NOT NULL,`name` VARCHAR(20) DEFAULT NULL,`phone` VARCHAR(20) DEFAULT NULL,`age` int(11) DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB
DEFAULT CHARACTER SET = ascii ROW_FORMAT = COMPACT;

当有一条记录是(1,“a”,“123”,18)的时候,由于使用的是 ASCII 字符集

  • name 占 6 个字节,转换成 16 进制就是 0x06
  • phone占 3 个字节,转换成 16 进制就是0x03
  • age 列和 id 列不是变长字段

这些变长字段的真实数据占用的字节数会按照列的顺序逆序存放(能够提高cpu的cache命中率),那这一条记录变长字段长度列表存储的值就是 03 06,如图所示

在这里插入图片描述

为什么要逆序存放?

答:

  1. 记录头信息中,指向下一条记录的指针,指向的是记录头信息和真实数据的中间位置,这样可以往左读就是记录头信息,右就是真实数据,比较方便
  2. 使得靠前的变长字段长度列表和真实数据可以尽量在同一个cpu的cache行中,提高cache的命中率

当表没有变长字段的时候,那么变长字段长度列表就不存在于行格式

🚓 Null值列表

通常情况下 NULL 值列表大小是 1 字节,也就是 8 bit,每个 bit 位表示一个字段

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

Null值列表对应的列也是按照逆序对应,如下图

在这里插入图片描述

举个例子,假设现在我有一条记录(1,“a”,“123”,null), id 有 NOTNULL 约束,所以不参与到 null值列表中来;name不为null,所以对应的是0;同理,phone对应的也是0;age字段为null,所以对应的是1;所以字段的顺序对应的null值列表是001因为要逆序存放,所以最终空值列表是100

  • 当表中所有字段都有NOT NULL约束时,那么就不存在 NULL 值列表
  • 当表中可以为 NULL 的字段大于 8 个,也就是8 bit不足以存下 Null 值列表的时候, Null 值列表就会扩展到 2 字节(8 bit),以此类推
🚁 记录头

如下图

在这里插入图片描述

  • delete_mark:行删除标记,在 innodb 中对于行数据的删除并不会马上去刷盘,而是先打上一个标记,待后续刷盘时机到了再把脏页刷入
  • min_rec_mark:B+树每层非叶子节点中最小的目录项记录会添加该标记(也就是目录页中主键值最小的记录的min_rec_mark是1,其他是0)。
  • record_type:记录类型,0 代表普通记录(记录数据),1 代表非叶子结点页中的记录(目录项记录),2 代表最小记录,3 代表最大记录。
  • n_owned:一个页有多条记录,这些记录会再进行分组(一个分组对应一个页的槽位),每个分组有一条记录会存储该分组有多少条数据,这个字段就是用来标记该分组有多少条记录的。
  • heap_no:当前记录在页中相对位置。
  • next_record:指向下一条记录的指针,这里可以对应到 B+树的结构特点。

🌌 真实数据

在这里插入图片描述

上图是 compact 行格式中记录的真实信息除了几个列值外,还有三个隐藏字段

🌍 隐藏字段
  • row_id:如果建表时指定了主键或者唯一约束,如果没有指定,那么 InnoDB 就会为记录添加 row_id 隐藏字段作为聚簇索引的键。,row_id 不是必须的
  • trx_id:事务id,表示这个数据是由哪个事务生成的,trx_id是必需的
  • roll_ptr:这条记录上一个版本的指针。roll_pointer 是必需的
🗻 存储的真正字段

按照顺序排放,null值字段被省略。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com