【Mysql】InnoDB 引擎中的页目录
一、页目录和槽
接上一篇,现在知道记录在页中按照主键大小顺序串成了单链表。
那么我使用主键查询的时候,最顺其自然的办法肯定是从第一条记录,也就是 Infrimum 记录开始,一直向后找,只要存在总会找到。这种在数据量少的时候还好说,一旦数据多了,遍历耗时一定非常长。
于是,作者又想到了一个好办法,灵感来自于书本中的目录。我们翻书的时候想查找一些内容,就会去查看目录,然后直接确定好内容所在的页码。
那么对于 InnoDB 来说,过程如下:
- 将所有正常的记录划分为几个组,这里包括那 2 条虚拟记录,但是不包含已经被移除到垃圾链表的记录。
- 每个组内最后一条记录(也就是最大的那条)就是“大哥”,其他记录都是“小弟”,而“大哥”记录的头信息中的 n_owned 属性表示该组内共有几条记录。
- 将每个组中最后一条记录在页面中的地址偏移量单独提取出来,按顺序存储到靠近页尾部的地方。
这个地方就是页目录 Page Directory。而上述的地址偏移量就是该记录的真实数据与页面中第 0 个字节之间的距离,这些地址偏移量被称为槽。
每个槽占用 2 字节,页目录就是由多个槽组成。
二、页目录的规定
在上一篇中,创建的表里存在 4 条数据,那么在页中还要算上 Infimum 和 Supremum,共 6 条记录。
这时候 InnoDB 会把它们分出 2 个组:
- 第一组:只有一个 Infimum 记录
- 第二组:剩下的 5 条记录
每个槽中,存放着每个组里最大的那条记录所在页面中的地址偏移量。
从图中,需要关注页目录的一些点:
- 页目录有 2 个槽,说明记录被分为 2 个组。
- Infimum 记录的 n_owned 属性值为 1,而 Supremum 的为 5。
为什么这 6 条记录要这样分?因为作者对于每组中的记录数量有规定:
- 对于 Infimum 所在的分组只能有 1 条记录。
- Supremum 所在的分组只能在 1~8 条之间。
- 剩下的分组,记录条数范围只能是 4~8 之间。
三、页目录查找记录的过程
现在继续向测试表里插入 12 条数据,也就是说在页中共有 18 条记录。
然后这些记录就被分成了 5 个组,这里参考书籍上的示意图(只保留一些关键属性):
现在,要查找主键是 6 的记录,要如何进行?
因为 5 个槽的编号分别为 0、1、2、3、4 挨着的,并且里面的主键值也都是从小到大进行排序的,可以使用二分法(不清楚的可以百度),那么初始情况下 low=0,high=4:
- 计算中间槽的位置,(0+4)/ 2=2,于是查看槽 2 对应记录的主键值为 8,因为 8 > 6,所以 high = 2,low 不变。
- 重新计算中间槽位置,(0+2)/ 2=1,于是查看槽 1 对应记录的主键为4,因为 4 < 6,所以 high 不变,low = 1。
- 因为 high - low = 1,所以确定主键值为6 的记录就在槽 2 对应的组中。接着找到该组中主键最小的记录,沿着单链表向后遍历,最终找到主键 6 的记录。
这里有个问题,槽对应的值都是这个组的主键最大的记录,如何找到组里最小的记录?比如槽 2 对应最大主键是 8 的记录,那如何找到最小记录。
解决办法是:
- 通过槽 2 找到 槽 1 对应的记录,也就是主键为 4 的记录。
- 主键为 4 的记录的下一条记录就是槽 2 当中主键最小的记录,可以找到主键 5。
总结
在一个数据页中查找指定主键值的记录,过程分为 2 步:
- 通过二分法确定该记录所在分组对应的槽,然后找到该槽所在分组中主键值最小的记录。
- 通过记录的 next_record 属性比那里该槽所在组的各个记录,最终找到目标记录。
本文参考书籍:
小孩子4919 《mysql是怎样运行的》
【Mysql】InnoDB 引擎中的页目录的更多相关文章
- 聊一聊 InnoDB 引擎中的索引类型
索引对数据库有多重要,我想大家都已经知道了吧,关于索引可能大家会对它多少有一些误解,首先索引是一种数据结构,并且索引不是越多越好.合理的索引可以提高存储引擎对数据的查询效率. 形象一点来说呢,索引跟书 ...
- InnoDB 引擎中的索引类型
首先索引是一种数据结构,并且索引不是越多越好.合理的索引可以提高存储引擎对数据的查询效率. 形象一点来说呢,索引跟书本的目录一样,能否快速的查找到你需要的信息,取决于你设计的目录是否合理. MySQL ...
- 巧用MySQL InnoDB引擎锁机制解决死锁问题(转)
该文会通过一个实际例子中的死锁问题的解决过程,进一步解释innodb的行锁机制 最近,在项目开发过程中,碰到了数据库死锁问题,在解决问题的过程中,笔者对MySQL InnoDB引擎锁机制的理解逐步加深 ...
- Innodb引擎中Count(*)
select count(*)是MySQL中用于统计记录行数最常用的方法,count方法可以返回表内精确的行数. 在某些索引下是好事,但是如果表中有主键,count(*)的速度就会很慢,特别在千万记录 ...
- Mysql InnoDB引擎下 事务的隔离级别
mysql InnoDB 引擎下事物学习 建表user CREATE TABLE `user` ( `uid` bigint(20) unsigned NOT NULL AUTO_INCREMENT, ...
- 聊一聊 InnoDB 引擎中的这些索引策略
在上一篇中,我们简单的介绍了一下 InnoDB 引擎的索引类型,这一篇我们继续学习 InnoDB 的索引,聊一聊索引策略,更好的利用好索引,提升数据库的性能,主要聊一聊覆盖索引.最左前缀原则.索引下推 ...
- 为什么 select count(*) from t,在 InnoDB 引擎中比 MyISAM 慢?
统计一张表的总数量,是我们开发中常有的业务需求,通常情况下,我们都是使用 select count(*) from t SQL 语句来完成.随着业务数据的增加,你会发现这条语句执行的速度越来越慢,为什 ...
- 【Mysql】InnoDB 引擎中的数据页结构
InnoDB 是 mysql 的默认引擎,也是我们最常用的,所以基于 InnoDB,学习页结构.而学习页结构,是为了更好的学习索引. 一.页的简介 页是 InnoDB 管理存储空间的基本单位,一个页的 ...
- MySQL存储引擎中的MyISAM和InnoDB区别详解
在使用MySQL的过程中对MyISAM和InnoDB这两个概念存在了些疑问,到底两者引擎有何分别一直是存在我心中的疑问.为了解开这个谜题,搜寻了网络,找到了如下信息: MyISAM是MySQL的默认数 ...
随机推荐
- 用Microsoft DirectX光线跟踪改善渲染质量
用Microsoft DirectX光线跟踪改善渲染质量 Implementing Stochastic Levels of Detail with Microsoft DirectX Raytrac ...
- 使用adb命令查看APP包名 和 包入口方法
方法一: 1.查看 前台应用 包名,使用此命令注意:手机只启动要查看包名的app adb shell dumpsys activity | find "mFocusedActivity&qu ...
- 【Javascript + Vue】实现对任意迷宫图片的自动寻路
前言 可以直接体验最终效果:https://maze-vite.vercel.app/ 寻路前: 寻路后,自动在图片上生成红色路径,蓝色是探索过的区域: 这里我故意用手机斜着角度拍,就是为了展示程序完 ...
- HashMap源码解析和设计解读
HashMap源码解析 想要理解HashMap底层数据的存储形式,底层原理,最好的形式就是读它的源码,但是说实话,源码的注释说明全是英文,英文不是非常好的朋友读起来真的非常吃力,我基本上看了差不多 ...
- 内核、dns、网卡配置
升级内核(安装新版软件包) rpm -ivh kernel-3.10.0-123.1.2.el7.x86_64.rpm 二.配置永久IP地址,子网掩码,网关地址 /etc/sysconfig/ne ...
- Spring Cloud专题之三:Hystrix
在微服务架构中,我们将系统拆分成很多个服务单元,各单位的应用间通过服务注册与订阅的方式相互依赖.由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问 ...
- vue调用子组件方法时,参数传不过去
有可能是因为子组件方法用了 async await 子组件去掉async就好了
- Qt5实现文本编辑器(附图片转PDF与详细代码)
1. 功能介绍 老规矩,我们直接上截图 这是主界面 文件菜单界面 编辑菜单界面 设置菜单界面 关于菜单界面 2. 功能演示 设置字体颜色 设置字体大小 点击关于菜单 点击关于Qt菜单 会自动跳转到Qt ...
- Spring官方发布新成员:Spring GraphQL
近日,在GraphQL Java诞生6周年的时候,Spring社区通过博客宣布正式创建全新项目:Spring GraphQL,同时还发布了这个新项目的里程碑1.0版本. 博客原文:https://sp ...
- hdu 2842 Chinese Rings 矩阵快速幂
分析: 后面的环能不能取下来与前面的环有关,前面的环不被后面的环所影响.所以先取最后面的环 设状态F(n)表示n个环全部取下来的最少步数 先取第n个环,就得使1~n-2个环属于被取下来的状态,第n-1 ...