【Mysql】InnoDB 引擎中的页目录

2024-01-12

一、页目录和槽
现在知道记录在页中按照主键大小顺序串成了单链表。

那么我使用主键查询的时候,最顺其自然的办法肯定是从第一条记录,也就是 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 属性比那里该槽所在组的各个记录,最终找到目标记录。

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 如何在不超时的情况下解析大型 CSV 文件?

    我正在尝试解析 50 MB 的 csv 文件 文件本身很好 但我正在尝试解决所涉及的大量超时问题 每个设置上传明智 我可以轻松上传并重新打开文件 但浏览器超时后 我收到 500 内部错误 我的猜测是我可以将文件保存到服务器上 打开它并保留我
  • 通过我的java代码导出数据库

    我想使用我的 java 代码导出我的 MySQL 数据库 但我还没有找到任何办法 我想要做的就是我的应用程序中有一个按钮作为 导出数据库 单击该按钮时 我的数据库应导出到指定的路径 我使用了以下代码 但它不起作用 Runtime runti
  • 在 MySQL 数据库中存储图像文件或 URL?哪个更好? [复制]

    这个问题在这里已经有答案了 可能的重复 在数据库中存储图像 是还是否 https stackoverflow com questions 3748 storing images in db yea or nay 数据库中的图像与文件系统中的
  • MySQL SELECT 输出同一行中每个 id 的下一个日期

    我查询的表结构如下 ID Date Before value After value 1 2014 04 25 Win Loss 1 2014 04 30 Loss Win 1 2014 08 18 Win Loss 1 2014 08 2
  • MYSQL 查询返回“资源 id#12”而不是它应返回的数值

    不知道为什么 但这返回了错误的值 我正在取回此资源 ID 12 而不是我正在寻找的数值 1 执行此操作的代码是 type SELECT account type from user attribs WHERE username userna
  • Codeigniter 加入多个条件

    我正在使用 Codeigniter Active Records 课程 我想加入我的users与我的桌子clients表 这样我就可以显示用户的 真实 姓名 而不仅仅是他们的 ID 这是什么clients表看起来像 示例 列 a 1 a 2
  • 通过连接从两个表中删除?

    我有两个表如下 tbl1 tbl2 id article id title image whole news tags author older datetime 其中 tbl1 id gt tbl2 article id 如何从两个表中删
  • MySQL 全文搜索不适用于某些单词,例如“house”

    我已经在 3 个字段中的一小部分记录上设置了全文索引 也尝试了 3 个字段的组合 并得到了相同的结果 有些单词返回结果很好 但某些单词如 house 和 澳大利亚 不这样做 有趣的是 澳大利亚 和 家乡 这样做 这似乎是奇怪的行为 如果我添
  • 如何将 MySQL 数据库更改为 UTC?

    我使用的是 Windows 7 对数据库方面的东西有点陌生 我尝试在 Google 上搜索如何将系统时区更改为 UTC 但文档有些高级 我不太确定如何更改此字段 在 my ini 文件的 mysqld 部分下 添加以下行 default t
  • 在 MacOSX10.6 上运行 python 服务器时 MySQLdb 错误

    运行我的服务器 python manage py runserver 产生以下错误 django core exceptions ImproperlyConfigured 加载 MySQLdb 模块时出错 没有名为 MySQLdb 的模块
  • ActiveRecord3死锁重试

    Rails 3 或 ActiveRecord 3 是否有任何插件可以复制旧版本死锁重试 http agilewebdevelopment com plugins deadlock retry插入 或者 该插件仍然适用于 Rails 3 吗
  • 如何在 phpmyadmin 中创建 MySQL 触发器

    我想在 MySQL 中创建一个触发器 我运行以下命令 mysql gt delimiter mysql gt CREATE TRIGGER before insert money BEFORE INSERT ON money gt FOR
  • 如何使用 MySQL 的 LOAD DATA LOCAL INFILE 在导入 CSV 时将字符串日期更改为 MySQL 日期格式

    我正在使用 MySQL 的 LOAD DATA LOCAL INFILE SQL 语句将数据从 CSV 文件加载到现有数据库表中 下面是一个 SQL 语句示例 LOAD DATA LOCAL INFILE file csv INTO TAB
  • Mysql 检索所有有限制的行

    我想检索特定用户的所有行 限制为 0 x 所以我只是想问是否有任何方法可以检索 mysql 中的所有行 而不调用返回 x 的 count id 的方法 而不重载现有函数 该函数在查询中根本没有限制 与我们的 string Relace 功能
  • 如何正确转义mysql?

    我刚刚发现如果我写 select from tbl where name like foo 然后添加 foo 作为参数及其值 a 用户数据 它不会正确转义 我勒个去 它想要 a 即使我使用参数 我还是忍不住觉得我对 sql 注入持开放态度
  • 使用 PHP 的 MySQL 连接字符串

    我正在尝试通过本地计算机连接到托管在我的服务器上的数据库 我的服务器有cPanel 11 它是一个典型的共享服务器 由CentOS提供支持 安装了PHP和MySQL 准确地说 我在同一台服务器上持有经销商帐户 我想在不同帐户或域之间访问数据
  • 如何在Sequelize中设置查询超时?

    我想看看如何在 Sequelize 中设置查询的超时时间 我查看了 Sequelize 文档以获取一些信息 但我找不到我要找的东西 我发现的最接近的是 pools acquire 选项 但我不想设置传入连接的超时 而是设置正在进行的查询的超
  • 将古吉拉特语文本插入 MySQL 表会产生垃圾字符和不可读的文本

    我有三个 MySQL 表 我正在向其中插入古吉拉特语内容 当我插入两个表时 它们插入得很好并且可读 但在一个表中 它显示垃圾字符 不可读的文本 我怎样才能解决这个问题 MySQL 有每个表的字符集设置 http dev mysql com
  • 在 MySQL 中使用 COUNT 时如何返回 0 而不是 null

    我使用此查询返回存储在 sTable 中的歌曲列表以及存储在 sTable2 中的总项目数 SQL queries Get data to display sQuery SELECT SQL CALC FOUND ROWS str repl
  • MySQL 查询计算上个月

    我想计算上个月的订单总额 我收到了从当前日期获取当月数据的查询 SELECT SUM goods total AS Total Amount FROM orders WHERE order placed date gt date sub c

随机推荐