Mysql知识体系小结 存储结构篇

本文详细解析了数据库页的存储结构,包括页的分类、内部结构(页头、页目录、用户记录等)、行格式的组成,以及索引和数据记录的组织方式。特别关注了页目录的二分查找优化和行中的记录头信息。

一、数据库的存储结构 页

1、概述

1、索引和数据记录信息都是保存在文件上的,(5.6之后使用独立表空间 ,innodb 在 /var/lib/mysql/数据库名/表名.ibd 文件中记录)

 

2、数据库中,不论读读取多少行,都是将这些行所在的页进行加载。

数据库管理存储空间的基本单位是页(Page 16KB) ,数据库IO的最小单位 是页

3、页与页之间是通过双向链表连接的,逻辑上连续,物理上不连续(区会连续分配64个页,保证顺序IO,这个后面再谈)。

数据页内的记录会按照主键从大到小的顺序组成一个单向链表,每个数据页都会为存储在它里面的记录生成页目录(槽的概念,将页内的遍历操作,变成二分查找,降低算法时间复杂度)。

#(没有自定义主键的时候,唯一性约束,会替代主键,都没有,则根据用户记录的隐藏列的row_id)

4、数据库存储结构   按照 行、页、区、段、表空间 依次上升。

2、页的内部结构

页有不同分类,我们常用的是聚簇索引叶子节点构成的数据页。

数据页16KB大小的存储空间被划分为7个部分:

文件头(38B)、页头(56B)、最大最小记录(26B)、用户记录、空闲记录、页目录、文件尾(8B)

(最大最小记录 和 用户记录,空闲记录构成了行记录)

FIle Header 描述各种页的通用信息(比如页编号,页的类型,其上一页,下一页是谁)

File Trailer :配合文件头的校验和字段,进行页同步的完整性校验。

-------------------------------------------------------------

Infirmum + Supremum  :是由5字节大小的记录头信息和8字节大小的一个固定的部分组成的

user Record  用户记录 按照指定的行格式 一条条的摆放在user Record,相互之间形成单链表

Free Record

---------------------------------------------------------------------

Page Directory  

在页中,记录是以单向链表的形式进行存储的。单向链表的特点就是插入、删除非常方便,但是检索效率不高,最差的情况下需要遍历链表上的所有节点才能完成检索。因此在页结构中专门设计了页目录这个模块,专门给记录做一个目录,通过二分查找法的方式进行检索,提升效率。

使用页目录,二分法查找
1. 将所有的记录分成几个组,这些记录包括最小记录和最大记录,但不包括标记为“已删除”的记录。
2. 第 1 组,也就是最小记录所在的分组只有 1 个记录;
    最后一组,就是最大记录所在的分组,会有 1-8 条记录;
    其余的组记录数量在 4-8 条之间。
这样做的好处是,除了第 1 组(最小记录所在组)以外,其余组的记录数会尽量平分。


3. 在每个组中最后一条记录的头信息中会存储该组一共有多少条记录,作为 n_owned 字段。


4. 页目录用来存储每组最后一条记录的地址偏移量,这些地址偏移量会按照先后顺序存储起来,每组的地址偏移量也被称之为槽(slot),每个槽相当于指针指向了不同组的最后一个记录(最大记录)

page Headr 

 为了能得到一个数据页中存储的记录的状态信息,比如本页中已经存储了多少条记录,第一条记录的地址是什么,页目录中存储了多少个槽等等,特意在页中定义了一个叫Page Header的部分,这个部分占用固定的56个字节,专门存储各种状态信息

3、行格式(记录格式)

记录的额外信息 +记录的真实数据 =一条完整记录

1、记录的额外信息

(1) 变长字段长度列表

表中某些字段是变长的 如 VARCHAR 、BLOB 我们除了要记录其真实值以外,还需要保存其实际的长度大小,该值就保存在 此未知。

注意 :存放顺序与实际数据 是逆序

(2)NULL列表

Compact行格式会把可以为NULL的列统一管理起来,存在一个标记为NULL值列表中。如果表中没有允许存储 NULL 的列,则 NULL值列表也不存在了。


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

注意 非空约束、主键 不需要记录, NULL列表也是逆序

(3)记录头信息(5个字节)

1、两个预留位 

2、delete_mask 

这个属性标记着当前记录是否被删除,占用1个二进制位。
值为0:代表记录并没有被删除
值为1:代表记录被删除掉了

3、min_rec_mask

4、record_type

这个属性表示当前记录的类型,一共有4种类型的记录:
   0:表示普通记录
   1:表示B+树非叶节点记录
   2:表示最小记录
   3:表示最大记录

5、heap_no

这个属性表示当前记录在本页中的位置。

一般来说 最小记录 和最大记录 分别是0,1,也就是说它们的位置最靠前。 我们自己插入的记录 是 2,3,4...

6、n_owned

页目录 对记录分组的时候,每组最后一条记录的n_owned 记录当前组有多少条数据。

7、next_record

记录头信息里该属性非常重要,它表示从当前记录的真实数据到下一条记录的真实数据的地址偏移量。

(4)记录真实数据

记录的真实数据除了我们自己定义的列的数据以外,还会有三个隐藏列

列名是否必须       占用字段描述
row_id6B行ID,唯一标识一条记录
transaction_id6B事务ID
roll_pointer7个字节回滚指针

一个表没有手动定义主键,则会选取一个Unique键作为主键,如果连Unique键都没有定义的话,则会为表默认添加一个名为row_id的隐藏列作为主键。所以row_id是在没有自定义主键以及Unique键的情况下才会存在的

一张图告诉你页的结构:

一张图告诉你用户记录的行格式结构

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值