MySQL-InnoDB页结构

一、索引页

在InnoDB中,数据是按页为单位进行存储的,一个页是16KB。如果概括的说,查询的逻辑就是 每次以页为单位读取数据到内存。然后再读取内存。

对于一个16K的数据页(官方叫索引页),其实并不都是存储的数据。如果存储的都是数据的话,不方便进行查询和分析。

所以呢,其实可以把数据页做一下拆分。使用一部分空间来存储汇总信息。

二、数据页结构

在InnoDB中,数据页分为以下模块。

结构名称描述
File Header文件头-用来存储页的一些通用信息
Page Header数据页专有的一些信息
Infimum、Supremum虚拟值 ,虚拟最大值,虚拟最小值 (这个值是数据库自己生成的一个标记)
User Record用户数据(真正用来存储数据)
Free Space空余空间
Page Directory页目录,在页目录中存储了一些数据的内存指针
File Trailer校验和

存储数据

数据存储在User Record中,具体的逻辑是 先从Free Space 中检查和申请空间,如果空间能够满足存储数据的要求,那么就划出这段空间用来存数据。那么,存储数据的空间,除了数据本身,还需要存储什么呢? 简单来说 每条存储的数据,除了数据本身,还有记录头信息。记录头信息主要有以下几个字段。

结构说明
预留位没用到
预留位2没用到
deleted_flag删除标记
min_rec_flagB+树中每层非叶子节点的最小的目录项记录都会添加该标记
n_owned每组中最大的数据该字段记录为组内数据条数,不是最大的数据,该数据通通为0
head_no当前记录的位置指针
record_type用来标记记录的类型,0-普通数据;1-非叶子节点的目录项记录;2-Infimum记录;3-Supremum记录
next_record下一条记录的相对位置。这个记录的其实是当前数据到下一条记录的真实距离,正值表示从当前地址向后找;负值表示从当前地址向前找,所以,他不是插入的顺序,而是按照主键大小排列的数据顺序。

还记得之前背八股文的时候,说 MySQL的数据是通过链表连接的。next_record就是串联的链表。

head_no

head_no 因为每条数据的长度不一样,而且数据是紧密排列的。每新增一条记录,head_no都加1,而head_no 为0 和1 ,被系统默认占用了。head_no =0 则指的是 Infimum数据(虚拟的最小数据值),head_no =1 指的是Supremum。记录的顺序呢?记录是按照主键的顺序进行排序的。

数据查找

现在呢,已经知道了,数据是按照从小到大的顺序排列的,那么怎么高效的查询呢?其实最容易想到的,就是从最小到最大的遍历,但是这样还是太慢了。在MySQL中,用的是类似于二分的查找。

有没有可能跳跃着记录一些数据的大小呢?这样,每比较一个数据,都可以跳过一些值,速度自然也就快了。

槽槽槽槽

在MySQL中,会将正常的数据分组,因为数据都是按顺序排的,这时候,每组的最后一条数据都是最大的,上边的表格,提到过n_owned,最大的数据的n_owned记录了这一组有多少条数据。而将每组的最大的数据都提出来,集中放到一起(放到页尾),这就实现了上边说到的,跳跃着比较数据。这集中放在一起的各组老大的页面偏移量,叫做槽,存放槽的地方叫做页目录。那这样,就实现实现了一个跳跃的,近似的二分查找。

具体的查询逻辑如下:

1、通过二分,确定中间的槽,根据槽的值大小,继续二分,直到确定了组,然后遍历这个组,就可以查询到数据啦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值