一、页目录和槽

接上一篇,现在知道记录在页中按照主键大小顺序串成了单链表。

那么我使用主键查询的时候,最顺其自然的办法肯定是从第一条记录,也就是 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:

  1. 计算中间槽的位置,(0+4)/ 2=2,于是查看槽 2 对应记录的主键值为 8,因为 8 > 6,所以 high = 2,low 不变。
  2. 重新计算中间槽位置,(0+2)/ 2=1,于是查看槽 1 对应记录的主键为4,因为 4 < 6,所以 high 不变,low = 1。
  3. 因为 high - low = 1,所以确定主键值为6 的记录就在槽 2 对应的组中。接着找到该组中主键最小的记录,沿着单链表向后遍历,最终找到主键 6 的记录。

这里有个问题,槽对应的值都是这个组的主键最大的记录,如何找到组里最小的记录?比如槽 2 对应最大主键是 8 的记录,那如何找到最小记录。

解决办法是:

  • 通过槽 2 找到 槽 1 对应的记录,也就是主键为 4 的记录。
  • 主键为 4 的记录的下一条记录就是槽 2 当中主键最小的记录,可以找到主键 5。

总结

在一个数据页中查找指定主键值的记录,过程分为 2 步:

  1. 通过二分法确定该记录所在分组对应的槽,然后找到该槽所在分组中主键值最小的记录。
  2. 通过记录的 next_record 属性比那里该槽所在组的各个记录,最终找到目标记录。

本文参考书籍:
小孩子4919 《mysql是怎样运行的》

【Mysql】InnoDB 引擎中的页目录的更多相关文章

  1. 聊一聊 InnoDB 引擎中的索引类型

    索引对数据库有多重要,我想大家都已经知道了吧,关于索引可能大家会对它多少有一些误解,首先索引是一种数据结构,并且索引不是越多越好.合理的索引可以提高存储引擎对数据的查询效率. 形象一点来说呢,索引跟书 ...

  2. InnoDB 引擎中的索引类型

    首先索引是一种数据结构,并且索引不是越多越好.合理的索引可以提高存储引擎对数据的查询效率. 形象一点来说呢,索引跟书本的目录一样,能否快速的查找到你需要的信息,取决于你设计的目录是否合理. MySQL ...

  3. 巧用MySQL InnoDB引擎锁机制解决死锁问题(转)

    该文会通过一个实际例子中的死锁问题的解决过程,进一步解释innodb的行锁机制 最近,在项目开发过程中,碰到了数据库死锁问题,在解决问题的过程中,笔者对MySQL InnoDB引擎锁机制的理解逐步加深 ...

  4. Innodb引擎中Count(*)

    select count(*)是MySQL中用于统计记录行数最常用的方法,count方法可以返回表内精确的行数. 在某些索引下是好事,但是如果表中有主键,count(*)的速度就会很慢,特别在千万记录 ...

  5. Mysql InnoDB引擎下 事务的隔离级别

    mysql InnoDB 引擎下事物学习 建表user CREATE TABLE `user` ( `uid` bigint(20) unsigned NOT NULL AUTO_INCREMENT, ...

  6. 聊一聊 InnoDB 引擎中的这些索引策略

    在上一篇中,我们简单的介绍了一下 InnoDB 引擎的索引类型,这一篇我们继续学习 InnoDB 的索引,聊一聊索引策略,更好的利用好索引,提升数据库的性能,主要聊一聊覆盖索引.最左前缀原则.索引下推 ...

  7. 为什么 select count(*) from t,在 InnoDB 引擎中比 MyISAM 慢?

    统计一张表的总数量,是我们开发中常有的业务需求,通常情况下,我们都是使用 select count(*) from t SQL 语句来完成.随着业务数据的增加,你会发现这条语句执行的速度越来越慢,为什 ...

  8. 【Mysql】InnoDB 引擎中的数据页结构

    InnoDB 是 mysql 的默认引擎,也是我们最常用的,所以基于 InnoDB,学习页结构.而学习页结构,是为了更好的学习索引. 一.页的简介 页是 InnoDB 管理存储空间的基本单位,一个页的 ...

  9. MySQL存储引擎中的MyISAM和InnoDB区别详解

    在使用MySQL的过程中对MyISAM和InnoDB这两个概念存在了些疑问,到底两者引擎有何分别一直是存在我心中的疑问.为了解开这个谜题,搜寻了网络,找到了如下信息: MyISAM是MySQL的默认数 ...

随机推荐

  1. CodeGen标记循环

    CodeGen标记循环 标记循环是一个模板文件构造,它允许您迭代CodeGen拥有的标记信息的集合.为了使用标记循环,必须基于至少定义了一个字段标记的存储库结构生成代码.              标 ...

  2. ADO.NET的五大对象

    ADO.NET是一种数据访问技术,使得应用程序可以连接到数据库存储,并以各种方式操作存储在其中的数据.该技术基于.NETFramework,与.NET Framework类库的其余部分高度集成. 其中 ...

  3. JVM系列(五):gc实现概要01

    java的一大核心特性,即是自动内存回收.这让一些人从繁琐的内存管理中解脱出来,但对大部分人来说,貌似这太理所当然了.因为现在市场上的语言,几乎都已经没有了还需要自己去管理内存这事.大家似乎都以为,语 ...

  4. csp-s模拟测试49(9.22)养花(分块/主席树)·折射(神仙DP)·画作

    最近有点头晕........... T1 养花 考场我没想到正解,后来打的主席树,对于每个摸数查找1-(k-1),k-(2k-1)...的最大值,事实上还是很容易被卡的但是没有数据好像还比较友善, 对 ...

  5. Java知识复习(一)

    Java面向对象的三大特性: 封装.继承.多态. super()与this()的区别? This():当前类的实例,一个类,如果继承了父类,那么通过this既可以访问当前类的属性和方法,也可以访问父类 ...

  6. 解决mac中adb: command not found

    在Mac系统中,很多时候第一次在Android SDK中使用adb的时候.无法使用.会提示-bash: abd: command not found. 造成此类现象的原因是:未配置Android的环境 ...

  7. WEB安全漏洞扫描与处理(下)——安全报告分析和漏洞处理

    1 AppScan生成的安全报告分析 利用AppScan生成安全报告,可以提前对要生成的安全报告的内容进行选择,如下图,最全的安全报告内容,包括摘要,安全性问题,咨询和修订建议,应用程序数据等. 生成 ...

  8. 在vue项目中使用echarts

    1.安装echarts依赖npm install echarts --save 2.在要使用的页面引入import echarts from 'echarts'v5之后使用 import * echa ...

  9. 没有指定非静态方法,Unity与Android通信错误

    报错信息: AndroidJavaException: java.lang.NoSuchMethodError: no non-static method with name='InstallApk' ...

  10. 《机器学习Python实现_10_10_集成学习_xgboost_原理介绍及回归树的简单实现》

    一.简介 xgboost在集成学习中占有重要的一席之位,通常在各大竞赛中作为杀器使用,同时它在工业落地上也很方便,目前针对大数据领域也有各种分布式实现版本,比如xgboost4j-spark,xgbo ...