MySQL索引底层实现原理(B树和B+树)

article/2025/9/8 23:58:15

文章目录

    • 一、B-树索引
      • 1. 理论部分
      • 2. B树
        • 黄色的data表示key索引所在的这一行的数据,data存储的是数据本身内容,还是数据在磁盘上的地址?
        • 关于操作系统从磁盘读取索引文件到内存中的几个问题
        • B树的缺点
    • 三、B+树
      • B+树特点
      • MySQL最终为什么要采用B+树存储索引结构?

一、B-树索引

1. 理论部分

数据库索引是存储在磁盘上的,当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘块(对应索引树的节点),索引树越低,越矮胖,磁盘IO次数就少

MySQL支持两种索引,一种的B-树索引,一种是哈希索引,B-树和哈希表在数据查询时的效率是非常高的。这里我们主要讨论一下MySQL InnoDB存储引擎,基于B-树(但实际上MySQL采用的是B+树结构)的索引结构。

B-树是一种m阶平衡树,叶子节点都在同一层,由于每一个节点存储的数据量比较大,所以整个B-树的层数是非常低的,基本上不超过三层。

由于磁盘的读取也是按block块操作的(内存是按page页面操作的,一般是16k,是内存页面的整数倍,读1块,刚好放到4个内存页面上),因此B-树的节点大小一般设置为和磁盘块大小一致,这样一个B-树节点,就可以通过一次磁盘I/O把一个磁盘块的数据全部存储下来,所以当使用B-树存储索引的时候,磁盘I/O的操作次数是最少的(MySQL的读写瓶颈,主要集中在磁盘I/O上

数据和索引都是放在磁盘上的,MySQL server得通过操作系统把磁盘上的数据加载到内存中。也就是说,运行起来的进程要访问索引,需要花费磁盘I/O,先把数据、索引读到内存中,而磁盘I/O很影响效率。

在C/C++中,如果我们new/malloc向内存申请4个字节,实际上不可能只拿4个字节,内存管理是按页面4K为大小单位的,操作系统相当于批发站,它批发内存是以页面为单位的,我们申请4个字节,实际上我们向内核kernel申请,内核是按页面给我们分配的。按页面分配以后,但是我们的应用程序只需要4个字节,还剩下的字节就被C函数库libc.so或者 libc++.so库的ptmalloc(缓存)tcmalloc来管理,相当于2个函数,负责管理剩下的空闲的字节,等你下次还malloc申请字节的时候,CPU就不用通过中断切换到内核态,直接在用户空间,从C库分配出来就可以了。等用光了,才向内核申请。

假设用AVL树存储20000000条数据,需要25层
在这里插入图片描述

在最坏的情况下,所有的数据都不在一个磁盘块上,读取所有的数据到索引树上,OS需要读取25次磁盘块。我们利用索引读取一条数据,最多需要查找25次

2. B树

在这里插入图片描述

涉及到磁盘到内存的一些读取,我们一般都采用B树结构。B树是平衡树,所有叶子节点都同在一层,B树是m阶平衡树(就是多叉AVL树),一般取值300-500。用B树来存储2千万的索引,假如m取500:

在这里插入图片描述
最多3层,最多3次磁盘I/O就可以了

在真实项目中,由于数据库表的数据数量会有所控制,构建的B+树也都不会超过3层,B树则可能会有4-5层

我们在student表中把uid设置为主键,会自动创建索引,当我们进行查询查询操作的时候

select * from student where uid=3;

使用索引查找过程:MySQL应用程序一看过滤条件的属性有索引,则先请求存储引擎,然后请求kernel,从磁盘上读uid的索引文件到内存上,然后拿读取的索引的数据构建B树来加速搜索

黄色的data表示key索引所在的这一行的数据,data存储的是数据本身内容,还是数据在磁盘上的地址?

  • 对于MyISAM而言,*.MYD*.MYI分别存储数据和索引,即数据和索引分开存放,所以在索引树上存放的只有实际数据在磁盘上的地址,而没有数据本身。

  • 对于InnoDB而言,*.idb存放的是数据和索引,数据和索引一起存放, 所以索引树上存放的就是数据本身。这就解释了为什么我们create table的时候不设置主键,InnoDB会自动生成主键,就是因为不建立索引就没有索引树,数据就没有地方存放。

关于操作系统从磁盘读取索引文件到内存中的几个问题

  1. 索引文件在磁盘上存储,磁盘的索引文件中的索引就是已经按B+树构建好的吗?

    答:那肯定不是,磁盘上只是存储的二进制文件,读取索引文件的时候,在内存上构建一颗B+树存放磁盘上读来的索引数据。数据结构都是在内存上表示的,没有说磁盘上构建个数据结构。

  2. 操作系统把磁盘的索引文件读到内存上构建B+树,如果磁盘的索引文件太大,内存读不下怎么办?那磁盘IO怎么算次数,现在不是都在内存上的B+树搜索读取数据了吗?

    答:先读索引文件的前几个字节,里面有第一个要读取的根节点数据在索引文件中的偏移量,读取根节点后,根据你要搜索的数据进行搜索,看是接着加载他的哪个孩子节点。 包括根节点的每一个节点,都存储了索引key值和它的孩子节点在磁盘上的位置偏移量信息。
    这样每一次搜索,最多只从根节点沿着某个路径加载到叶子节点上,而不可能是整个索引文件都加载到内存

  3. 在B树和AVL树上搜索一个数据都是O(log2N),为什么还要使用B树?

    答:我们读取数据总共分为两步:花费磁盘I/O把数据从硬盘读到内存,在内存上构建B树,然后到B树上搜索。虽然在内存上搜索的时间都是O(log2N),但B树高度更低,花费的磁盘I/O更少,速度更快

问题总结:索引文件在磁盘上是二进制的,但是文件中存储了根节点的key值和这个节点的整个的偏移量,还存储的它的左右孩子的key值和整个节点的偏移量。操作系统从磁盘的索引文件中,一次读取一个block块的大小(最好是一个节点大小)到内存中构建B+树,然后在节点中二分搜索元素,如果发现值大于根节点的所有数据值,那么就继续从磁盘的索引文件中把该节点的右孩子节点加载到内存上,然后进行二分搜索查找,以此类推下去。

举个搜索的例子

select * from student where name = "zhangsan";

如果name没有索引,在MyISAM中(索引和数据分开存放),就是把整张表过1遍,效率非常低。加个limit 1,就是找到第一个符合条件的数据,就会停止查找,效率提高一些

如果我们给name建索引,当我们再去执行这个select语句的时候,MySQL server就知道name有索引,直接加载name的索引文件,花费磁盘I/O,把磁盘上的索引(name)加载到内存中来,以二分查找的方式(会比较索引的大小关系)构建成B-树。

B树的缺点

每个节点中有key(索引),也有data(对于MyISAM来说是数据的地址,对于InnoDB来说是数据本身),但是每一个节点的存储空间是有限的,data占用较大时,会导致每个节点存储的key就会减少(即树的分支变少),同样会导致B树的高度较大,磁盘IO次数花费增大,效率降低!!!

三、B+树

在这里插入图片描述

B+树特点

  1. 非叶子节点相当于是叶子节点的索引,不存储数据,叶子节点用于存储关键字以及数据。 即每个B+树非叶子节点相对于B树的叶子节点能存储更多的key,这样树的高度就更低,花费的磁盘I/O就更少,查找更快。
  2. 由于数据全部存在于叶子节点,所以无论查找哪个数据,花费的磁盘I/O次数都是一样的,查找数据耗费的时间比较稳定
  3. 叶子节点被串在链表中,形成了一个有序链表。做范围搜索和整表遍历的时候直接遍历这个有序链表即可,不用遍历平衡树

MySQL最终为什么要采用B+树存储索引结构?

  1. 在B树中搜索时,离根节点近的节点找的就快,离根节点远的节点找的就慢,查找数据花费的时间不稳定。B+树所有的数据都在叶子节点,查找数据花费的时间稳定
  2. B树的每一个内部节点,都存了key和对应的数据。而B+树的非叶子节点只存关键字,不存数据,B+树的叶子节点存放key和数据。节点的大小是一个块的大小,在节点大小相同的情况下,由于B+树的非叶子节点不存储数据,存储的关键字(key)会远远多于B树,因此,B+树的高度要小于B树,使用的磁盘I/O次数少,查询更快。
  3. 节点内存在的索引值越多,相邻索引值之间的区间就会越小,查找范围越小,查找的就越容易。而B树非叶子节点相邻索引值之间的区间比B+树要大
  4. B树不方便做范围搜索(where age between 10 and 20),整表遍历也不方便。而B+树将所有的叶子节点都串在链表上,做区间搜索以及整表遍历比平衡树快

当我们回答问题的时候,不要1 2 3这样把答案背出来,这样效果是很差的,我们回答索引的底层原理的时候可以这样回答:

当我们select * from student where name="zhangsan"的时候,数据库引擎会检查name字段有没有索引

若没有索引数据库引擎会做整表搜索,效率是比较低的。

如果有索引,数据库引擎会向内核申请从磁盘上读取索引文件到内存,一个节点一个节点在内存上构建B+树,一个节点对应一次磁盘I/O。非叶子节点只存关键字key,所有的key和data都会出现在叶子节点,所以用B+树构建索引树,会以最少的磁盘I/O构建出来。其次搜索的时候是以二分的方式进行搜索的,O(log2N)的效率还是很高的。甚至还可以解释一下为什么使用B+树而不使用B树。


http://chatgpt.dhexx.cn/article/28JsqkCI.shtml

相关文章

B树概念和插入实现

目录 前言 一.B树概念 1.1 概念和性质 1.2 分裂 二.插入的实现 三.性能分析 四.B树的删除 五.B树的优化B树和B*树 5.1 B树 5.2 B*树 六.B树的应用 6.1 MyISAM中的索引 6.2 Innodb引擎 前言 之前我们学了有很多数据结构,比如顺序表,链表,…

MySQL索引(B树、B+树)

目录 简介索引结构(树)为什么用树,而不用哈希表BTree索引BTree索引聚簇索引与非聚簇索引 索引分类性能分析索引创建场景 简介 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。可…

MySQL B+树相对于B树的区别及优势:

部分参考:B树和B树的区别 MySQL为什么使用树结构? 文件很大,不可能全部存储在内存中,故要存储到磁盘上索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数(为什么使用B-/Tree,还跟磁盘存取原理有关&am…

B树索引

B-Tree索引是最常见的索引结构,如oracle和mongodb的索引都是B-Tree,而mysql的索引类型是BTree 一、B树索引的结构 B-树索引是基于二叉树结构的。B-树索引结构有3个基本组成部分:根节点、分支节点和叶子节点。其中根节点位于索引结构的最顶端…

什么是B树

1.什么是B树 B树又称为多路平衡查找树,B树中所有结点的孩子节点数的最大值称为B树的阶,通常用m表示。 2.B树的特性 一颗m阶B树或为空树,或为满足如下特性的m叉树: 1)树中每个结点至多有M棵子树(即至多含有…

图解B树构建过程

1.B树结构同时满足以下特性 每个节点最多包含n个孩子,即n叉树;除了根节点和叶子节点外,每个节点至少有ceil(n/2)个孩子(ceil是向上取整);若根节点不是叶子节点,则至少有两个孩子;所…

了解B树的删除

文章目录 1. 删除操作第一种情况第二种情况第三种情况 2. C示例3. 删除复杂度参考文档 在本教程中,您将学习如何从B树中删除键。此外,您还可以找到C语言的示例。     删除B树上的元素包括三个主要事件:搜索要删除的键所在的节点、删除键和…

B树的插入、删除操作

一、简介 B树是什么? 1970年,R.Bayer和E.mccreight提出了一种适用于外查找的树,它是一种平衡的多叉树,称为B树(或B-树、B_树)。 一棵m阶B树(balanced tree of order m)是一棵平衡的m路搜索树。它或者是空树…

数据结构-B树删除示例

数据结构学习-B树删除示例 1、B树简介2、在线可视化生成B树工具3、B树删除规则4、B树删除示例4.1、删除非根结点示例4.2、删除根结点示例 1、B树简介 1970年,R.Bayer和E.mccreight提出了一种适用于外查找的树,它是一种平衡的多叉树,称为B树&a…

B树-多路平衡查找树

B树 B树一个m阶B树的具有的特征(或必须满足的条件)B树的查找B树插入元素(一定是在叶子节点插入)1.插入后,没有破坏B树的规则2.插入后,叶子节点元素超过m-1个 B树删除元素1.删除叶子节点上的元素,没有破坏规则2.删除叶子…

B树、B+树详解

B-树,即为B树。因为B树的原英文名称为B-tree,目前理解B的意思为平衡。 概念 首先,B树不要和二叉树混淆,在计算机科学中,B树是一种自平衡树数据结构,它维护有序数据并允许以对数时间进行搜索,顺…

【B树及B树的基本操作】

文章目录 1.B树的定义和特性2.B树的性质3.B树创建的过程。4.B树的删除5.总结 1.B树的定义和特性 B树是一种平衡的多路查找树。 一棵m阶的B树(B树中所有结点的孩子个数的最大值为m),或为空树,或为满足下列特性的m叉树: (1) 树中每…

B树和B+树的区别

文章目录 简述写在前面1、B树2、B树 深入浅出B树B树深入B-树的查找 B 树B树概述 B-树和B树的区别拓展:MySQL为什么使用B-Tree(BTree)&& 存储知识存储数据最小单元主存存取原理磁盘存取原理 总结 简述 写在前面 大家在面试的时候&am…

B树(B-树)详解

B-树,即为B树。因为B树的原英文名称为B-tree,而国内很多人喜欢把B-tree译作B-树,B-tree就是指的B树。 B-树容易让人误解,建议大家用B树称呼, 本文以下直称B树 这篇介绍概念, 优点应用等, B树的描述和增删改查请到隔壁我写的另一篇(篇幅较长…

数据结构 —— B树

文章目录 1、B树的定义1.1、B树的特性1.2、B树的高度1.3、性能分析1.4、B树的补充说明1.5 、B树、B-树 、B-tree、B tree的区别 2、B树的插入操作以5阶B树为例,介绍B树的插入操作, 3、 B树的删除操作以5阶B树为例,介绍B树的删除操作 4、B树相…

B树和B+树详解

B树、B树看这一篇就够了 [TOC](B树、B树看这一篇就够了) 引言B树什么是B树以及B树是怎么来的B树的基本性质B树的新增和删除B树的插入B树的删除 B树什么是B树以及为什么要有B树B树的基本性质B树的查找 B树与B树的比较B树的优势B树的优势两者的细节对比 B树与B树在实际代码中的应…

B-树(B树)详解

https://www.jianshu.com/p/7dedb7ebe033 具体讲解之前,有一点,再次强调下:B-树,即为B树。因为B树的原英文名称为B-tree,而国内很多人喜欢把B-tree译作B-树,其实,这是个非常不好的直译&#xf…

B树和B+树

目录 一、BST树到AVL树到B树的简介 1.1 BST树 --- 二叉排序树 1.2 AVL树 --- 平衡二叉树 1.3 B树 --- 平衡多路查找树 1.3.1 B树的查找结点过程 1.3.2 B树的添加结点过程(和结点分裂过程) 1.3.3 B树的删除结点过程 二、B树 2.1 B树和B树 一…

在群晖NAS部署_开源在线项目任务管理工具【dooTask】

一、dooTask简介 1.1、说明 Dootask 是一款由国人开源的轻量级在线项目任务管理工具,它提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时通讯IM,文件管理等功能。基于PHP与Vue编写,遵守AGPL3.0开源协议。 1.2、特…

软件项目管理的重点知识

软件项目管理的重点知识 1.软件项目管理概述 1.1项目是什么 项目是为了创造一个唯一的产品或提供一个唯一的服务而进行的临时性的努力。 1.2常见的项目 生活中的项目 生日聚会野餐活动集体婚礼 大项目 微软的操作系统阿波罗计划神州飞船计划鸿蒙操作系统开发一个网站运…