MySQL数据库精研之旅第十四期:索引的 “潜规则”(上)

专栏:MySQL数据库成长记

个人主页:手握风云

目录

一、索引简介

1.1. 索引是什么

1.2. 为什么需要索引

二、索引应该选择哪种数据结构

2.1. Hash

2.2. 二叉搜索树

2.3. N叉树

2.4. B+树

三、MySQL中的页

3.1. 为什么要使用页

3.2. 页文件头和页文件尾

3.3. 页主体

3.4. 页目录

3.5. 数据页头

四、B+树在MySQL索引中的应用

4.1. 计算三层树高的B+树可以存放多少条记录


一、索引简介

1.1. 索引是什么

        MySQL的索引是⼀种数据结构,它可以帮助数据库高效地查询、更新数据表中的数据。索引通过⼀定的规则排列数据表中的记录,使得对表的查询可以通过对索引的搜索来加快速度。不同的数据结构由于实现的算法不同,最终不同数据结构查询的时间复杂度和空间复杂度也不同。

        MySQL索引类似于书籍的⽬录,通过指向数据行的位置,可以快速定位和访问表中的数据,比如汉语字典的目录(索引)页,我们可以按笔画、偏旁部首、拼音等排序的目录(索引)快速查找到需要的字。

  • 笔画索引

        当字典中要收录一个字的时候,不但要把字放在字典的合适位置,同时也会更新索引。有多少个索引,就需要更新多少个索引。字典收录字的时候按组织数据的规则把字安排在一个合适的位置,查询是按同样的规则进行检索。索引就是确定了组织数据的方式,不同的索引类型组织数据的方式不同。

1.2. 为什么需要索引

        显而易见,使用索引的目的只有一个,就是提升数据检索的效率,在应用程序的运行过程中,查询操作的频率远远高于增删改的频率。MySQL最主要的功能就是存储数据,同时在保证安全的前提下尽量提升查询效率。

二、索引应该选择哪种数据结构

2.1. Hash

        时间复杂度O(1),查询速度非常快。MySQL并没有把Hash当成默认索引使用的数据结构,原因是Hash不支持范围查找。

2.2. 二叉搜索树

        二叉搜索树中序遍历之后得到一个有序序列,最坏情况下退化为一棵单边数,时间复杂度为O(n)。由于数据保存在磁盘上,每一次通过父节点去找子节点,就会发生一次磁盘IO,磁盘I0是制约整个数据库甚至是应用程序性能的主要因素。

        二叉树的度是2,当节点特别多的时候无法保证树的高度,当树越高发生磁盘IO的次数就越多,数据库的性能就越差。

2.3. N叉树

        N叉树解决了树高的问题,从而减少磁盘IO的次数,并且支持范围查找。

2.4. B+树

        B+树是一种经常用于数据库和文件系统等场合的平衡查找树,MySQL索引采用的数据结构。

  • B+树与B树的区别:
  1. 叶子节点之间有一个相互连接的引用,可以通过一个叶子节点找到与它相邻的兄弟节点,因为MySQL在组织叶子节点时使用的是双向循环链表。
  2. 非叶子节点中的值都包含在叶子节点中。B+树的非叶子节点中只包含对子节点的引用,没有保存真正的数据,所有真实数据都保存在叶子节点中。
  3. 对于B+树而言,在相同树高的情况下,查找任一元素的时候复杂度都一样,性能均衡。

        使用了B+树能够保持数据稳定有序,插入与修改有较稳定的时间复杂度O(logn)。B+树的叶子节点可以按一KEY进行排序,保证了数据的有序性,从而可以支持范围查找。

三、MySQL中的页

3.1. 为什么要使用页

        在.ibd 文件中最重要的结构体就是Page(页),页是内存与磁盘交互的最小单元、默认大小为16KB每次内存与磁盘的交豆至少读取一页,所以在磁盘中每个页内部的地址都是连续的,之所以这样做,是因为在使用数所以一次从磁据的过程中,根据局部性原理,将来要使用的数据大概率与当前访问的数据在空间上是临近的盘中读取一页的数据放入内存中,当下次查询的数据还在这个页中时就可以从内存中直接读取,从而减少磁盘IO提高性能。

        MySQL中的页是由操作系统中的4个页拼装在一起的。当我们执行一条SQL语句时,每次查询都要把16kb的页全部查出来,这是由于时间局部性和空间局部性。如果一个信息项被访问,那么近期内还可能会被访问,将来要用到的信息大概率与正在使用的信息在空间地址上是临近的。

3.2. 页文件头和页文件尾

        页文件头和页文件尾包含的信息,如下图所示:

        这里我们只关注,上一页页号和下一页页号,通过这两个属性可以把页与页之间链接起来,形成一个双向链表。

3.3. 页主体

        页主体部分是保存真实数据的主要区域,每当创建一个新页,都会自动分配两个行,一个是页内最小行Infimun ,另一个是页内最大行 Supremùn,这两个行并不存储任何真实信息,而是做为数据行链表的头和尾,第一个数据行有一个记录下一行的地址偏移量的区域 next_record 将页内所有数据行组成了一个单向链表,此时新页的结构如下所示:

        最小行与最大行之间从哪开始到哪结束,中间不储存任何数据。

        当向一个新页插入数据时,将 Infimun 连接第一个数据行,最后一行真实数据行连接 supremun ,)这样数据行就构建成了一个单向链表,更多的行数据插入后,会按照主键从小到大的顺序进行链接,如下图所示:

        页中的数据行之间是单向链表的关系,并且是有序的。

3.4. 页目录

        一个页有16kb,可以存很多数据行,在一个页中进行数据行的遍历也很费时,如何优化?

  • 当按主键或索引查找某条数据时,最直接简单的方法就是从头行infimun开始,沿着链表顺序逐个比对查找,但一个页有16KB,通常会存在数百行数据,每次都要遍历数百行,无法满足高效查询,为了提高查询效率,InnoDB采用二分查找来解决查询效率问题;
  • 具体实现方式是,在每一个页中加入一个叫做页目录Page Directory 的结构,将页内包括头行、尾行在内的所有行进行分组,约定头行单独为一组,其他每个组最多8条数据,同时把每个组最后一行在页中的地址,按主键从小到大的顺序记录在页目录中在,页目录中的每一个位置称为一个槽,每个槽都对应了一个分组,一旦分组中的数据行超过分组的上限8个时,就会分裂出一个新的分组;
  • 后续在查询某行时,就可以通过二分查找,先找到对应的槽,然后在槽内最多8个数据行中进行遍历即可,从而大幅提高了查询效率,这时一个页的核心结构就完成了;
  • 例如要查找主键为6的行,先比对槽中记录的主键值,定位到最后一个槽2,再从最后一个槽中的第一条记录遍历,第二条记录就是我们要查询的目标行。

        先在页中建立一个页目录,页中有很多的分组,当一个分组中的数据行大于8时,会自动拆分出另一个分组,同时在页目录中建立槽。槽和分组是一一对应的关系,槽里记录了当前分组最后一条记录的主键值。要想查询id = 7的记录,首先判断槽中的值,找到数据可以存在的分组再去分组中逐条的比对,最终找到目标行。

3.5. 数据页头

        数据页头记录了当前页保存数据相关的信息,如下图所示:

四、B+树在MySQL索引中的应用

        非叶子节点保存索引数据,叶子节点保存真实数据,以下B+树表示的是表中的主键索引:

        数据行的排列方式是从左到右,从上到下去组织,插入一条数据时把数据行安排在合适的位置即可。

        以查找id为5的记录,完整的检索过程如下:

  1. 首先判断B+树的根节点中的索引记录,此时5 < 7 ,应访问左孩子节点,找到索引页2​;
  2. 在索引页2中判断id的大小,找到与5相等的记录,命中,加载对应的数据页​;

        以上的例子3次磁盘10就可以找到数据行,还可以把索引页缓存到内存,进一步提升效率。

4.1. 计算三层树高的B+树可以存放多少条记录

  • 假设一个数据行大小为1kb,一页就可以存16条数据;
  • 索引页一条数据大小:主键用bigint类型占8byte,下一页地址假设6byte,一共是14byte,一个索引页就可以保存1024*16/14 = 1170;一个索引页的度是1170,也就是可以有1170个子节点;
  • 如果只有三层树高的情况,综合只保存索引的根节点和二级节点的索引页以及保存真实数据的数据页,那么一共可以保存1170 * 1170 * 16=21,902,400条记录,也就是说在两千多万条数据的表中,可以通过三次IO就完成数据的检索​;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/97209.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/97209.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

架构设计——云原生与分布式系统架构

** 云原生与分布式系统架构** 5.1 云选型策略&#xff1a;多云、混合云还是单云&#xff1f;如何决定&#xff1f; “上云”已无需讨论&#xff0c;但“上什么云”是第一个战略决策。单云&#xff08;Single Cloud&#xff09;策略&#xff1a; 描述&#xff1a; 将全部资源集中…

Python图片转WebP常用库推荐:Pillow、Wand、cv2

摘要 Python转换图片为WebP&#xff0c;Pillow最推荐&#xff1a;安装简单&#xff08;pip install pillow&#xff09;、使用方便&#xff0c;代码示例显示处理RGBA转RGB等细节&#xff0c;适合多数场景&#xff1b;Wand功能更强基于ImageMagick&#xff0c;适合需高级处理的场…

Android WPS Office 18.20

WPS Office是一款集Word&#xff0c;PDF&#xff0c;Sheet&#xff0c;PowerPoint&#xff0c;表格&#xff0c;文档&#xff0c;云存储&#xff0c;模板库和在线编辑与共享于一体的多功能免费办公套件。它提供类似于Microsoft Office的功能&#xff0c;包括文字处理、表格编辑…

Elasticsearch核心配置与性能优化

以下是Elasticsearch&#xff08;ES&#xff09;的 核心配置项 及 性能优化措施&#xff0c;涵盖硬件、系统、ES配置、索引设计等关键方面&#xff0c;帮助提升集群稳定性与查询性能&#xff1a;一、硬件与系统层优化内存分配 堆内存&#xff08;Heap Size&#xff09;&#xf…

【谷歌浏览器】浏览器实用自用版——谷歌浏览器(Google Chrome)离线纯净版安装 官方版无任何捆绑及广告 【离线安装谷歌浏览器】

经常上网的朋友们肯定深有体会&#xff1a;如今不少浏览器动不动就弹广告、塞插件&#xff0c;用起来简直是折磨。面对这些“全家桶”式捆绑&#xff0c;大家都渴望能找到一款干净、简洁、无打扰的浏览器——这时候&#xff0c;Google Chrome&#xff08;谷歌浏览器&#xff09…

2025年渗透测试面试题总结-39(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 3. SAST&#xff08;静态应用安全测试&#xff09; 4. IAST&#xff08;交互式应用安全测试&#xff09; …

网站测试报告:WEB应用反CSRF的本质与防御机制

CSRF (跨站请求伪造) 本质&#xff1a; 攻击者诱骗已登录目标站点的用户&#xff0c;在不知情的情况下提交一个恶意请求。该请求利用用户浏览器中已存储的认证信息&#xff08;如Cookie、Session&#xff09;&#xff0c;以该用户的身份执行未授权的操作&#xff08;如修改密码…

2025年9月计算机二级C++语言程序设计——选择题打卡Day10

备考计算机二级 C 程序设计考试&#xff0c;选择题是不容忽视的重要部分。 今天为大家带来 10 道难点选择题&#xff0c;聚焦继承、多态等核心难点&#xff0c;助力提升解题精度。 1、有如下程序&#xff1a; #include<iostream> using namespace std; class Base { pub…

Formdata表单数据提交

前言&#xff1a;在表单数据提交中&#xff0c;常常除了字符串拼接的方式传给后端&#xff0c;一般可能还需要使用Fromdata的格式包装所要提交的表单数据传递。常用场景&#xff1a;表单数据提交一、Formdata的优势使用 FormData 主要是因为它有两个独特优势&#xff1a;能轻松…

React Native 初体验

前言 最近公司需要移植一个应用到 iOS 端&#xff0c;本来想要尝试 uniapp 的新架构 uniapp-x 的&#xff0c;折腾两天放弃了&#xff0c;选择了 React Native。 原因&#xff1a; HbuilderX 中的 uniapp-x 模版过于臃肿&#xff0c;夹杂很多不需要的东西&#xff08;可能是…

自动驾驶中的传感器技术36——Lidar(11)

本章节重点介绍和FMCWOPA Lidar强相关的硅光技术。 1、硅光技术概述&#xff08;Silicon Photonics&#xff09; 硅光技术主要是用在光通信中&#xff0c;利用硅作为光学介质&#xff0c;通过光传输和处理数据。与依赖电子进行数据传输的传统电子电路不同&#xff0c;硅光子学…

MapStruct用法和实践

一、MapStruct 用法1. 嵌套对象深度映射&#xff08;Deep Mapping&#xff09;// 源对象 public class User {private Address address;// getter/setter }public class Address {private String city;private String street; }// 目标对象 public class UserDTO {private Stri…

设计模式相关面试题

写在前面 &#x1f525;我把后端Java面试题做了一个汇总&#xff0c;有兴趣大家可以看看&#xff01;这里&#x1f449; ⭐️在反复复习面试题时&#xff0c;我发现不同资料的解释五花八门&#xff0c;容易造成概念混淆。尤其是很多总结性的文章和视频&#xff0c;要么冗长难…

访问者设计模式

访问者设计模式是一种行为模式&#xff0c;允许您向现有对象结构添加新作&#xff0c;而无需修改其类。 它通过允许您将算法与其作的对象分开来实现这一点。 它在以下情况下特别有用&#xff1a; 您有一个复杂的对象结构&#xff08;如 AST、文档或 UI 元素&#xff09;&#x…

Linux_用 `ps` 按进程名过滤线程,以及用 `pkill` 按进程名安全杀进程

用 ps 按进程名过滤线程&#xff0c;以及用 pkill 按进程名安全杀进程摘要&#xff1a; 过滤线程信息&#xff1a;教你用 ps -C、pgrepps 等多种姿势&#xff0c;既精准又避免误杀。按名字杀进程&#xff1a;用 pkill 一把梭&#xff0c;优雅还是强杀随你选&#xff0c;附带“先…

关于国产 RAC 和分布式研讨

本次研讨核心目标是围绕崖山 DB、达梦 DB、GBASE三款国产数据库&#xff0c;以及数据库内核开发吕工程师的分享&#xff0c;深入了解共享集群 RAC 的开发技术。但实际效果未达预期&#xff0c;参会者多围绕 “共享集群与分布式应用场景” 泛泛而谈&#xff0c;缺乏深度技术拆解…

传输层协议介绍

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档文章目录前言一、TCP协议介绍二、TCP报文格式三、TCP三次握手四、TCP四次挥手五、UDP协议介绍六、常见协议及其端口七、TCP与UDP的不同总结前言提示&#xff1a;这里可以添加本…

Vibe Coding 概念提出者 AndrejKarpathy 谈强化学习。

在预训练时代&#xff0c;关键在于互联网文本。你最需要的是一大批量、多样化且高质量的互联网文档&#xff0c;供模型从中学习。在监督微调&#xff08;SFT&#xff09;时代&#xff0c;核心则是对话数据。人们雇佣合同工人为问题撰写答案&#xff0c;类似于你在 Stack Overfl…

OSI模型和TCP/IP模型区别是什么

问题OSI模型和TCP/IP模型区别是什么我的回答OSI和TCP/IP这两个协议栈有几个主要区别&#xff1a;首先&#xff0c;层次结构不同。OSI是七层模型&#xff1a;物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。而TCP/IP是四层模型&#xff1a;数据链路层、网络层、传…

ros2与gazebo harmonic机械臂仿真项目Moveit2YoloObb的优化

文章目录 关于项目RVIZ控制Gazebo Harmonic仿真机械臂GraphExecuter创建流程并通过Yolo算法抓取螺栓 关于项目 本文介绍ros2与gazebo harmonic机械臂仿真项目Moveit2YoloObb优化的内容&#xff0c;具体的代码细节就不赘述了&#xff0c;主要还是演示效果&#xff0c;包括RVIZ控…