MySQL 索引原理

索引类似字典目录,通过目录可以快速高效的找到想要的内容,总得来说是一种通过空间换时间提高查询效率的方案。它常包含以下几种实现:

  • Hash 类型
  • B 树类型
  • B+ 树类型

首先对于 Hash 类型来说,它只适合单 key 查询,不能做范围查询(不能对索引值排序),一般很少使用

平衡二叉树具有极高的查询效率,每次判断,只需向左或者向右即可,时间复杂度 log2n。然而由于每个节点只能保存一条数据,对于数据库这种海量数据来说,树的高度太高导致磁盘 I/O 的次数过多,再加上为了维持树的平衡所需的左旋、右旋操作,整体效率很差,这也是为什么索引不使用平衡二叉树或者红黑树的主要原因

B 树实际就是二叉树的进一步变种,它的每个节点可以保存多条数据,并且包含多个指向子节点的引用,维护有序数据并允许顺序访问、插入和删除,比较契合磁盘预读逻辑,更适合读取、写入相对较大的数据块,非常适用于数据库和文件系统

B- 树实际就是 B 树,这块是因为翻译问题

B 树是一种平衡多叉树,对于 m 阶的 B 树,它必须满足以下条件:

  1. 每个节点最多包含 m 个子节点
  2. 非根节点至少有 m / 2 个元素
  3. 如果根节点不是叶子节点,则至少包含两个子节点
  4. 具有 k 个子节点则包含 k - 1 个元素
  5. 所有叶子节点必须处于同一水平

对于插入操作,每次在根节点对应位置插入,之后根据以下规则进行调整:

  1. 若该节点元素个数小于 m - 1,直接插入
  2. 若该节点元素个数等于 m - 1,引起节点分裂,取中间元素插入到父节点中
  3. 重复步骤二,直到所有节点符合 B 树的规则,最坏的情况一直分裂到根节点,生成新的根节点,高度增加 1

下面以 3 阶 B 树为例,分别介绍上面三种情况:

  • 场景1:直接添加,无须任何处理
    在这里插入图片描述
  • 场景2:分裂,中间节点分裂为父节点
    在这里插入图片描述
  • 场景3:多次分裂,产生新的父节点
    在这里插入图片描述

注意,上面只是为了画图方便,实际场景中 B 树是这样的:
在这里插入图片描述
一个节点如果包含 k 个元素,就包含 k + 1 个子节点引用,上面把这块省略掉了

对于删除操作,首先在 B 树中查找需删除的元素,如果存在就删除,删除后根据以下规则进行调整:

  • 被删除元素位于叶子节点且删除后节点中元素数目小于 m / 2,则需要看其相邻兄弟节点是否丰满:如果丰满,则向父节点借一个元素来满足条件(丰满节点提交一个到父节点)、如果都不丰满,父节点下放一个元素,并和其子节点合并为一个新节点,合并完成后父节点也要判断是否需要继续合并
  • 如果被删除元素位于非叶子节点,则将它的下一个节点上移,最终相当于删除某个根节点元素,删除会执行上述规则

下面同样以 5 阶 B 树为例,分别演示几种情况:

  • 场景一:正常删除,无影响
    在这里插入图片描述
  • 场景二:被删除元素在叶子节点,相邻节点丰满
    在这里插入图片描述
  • 场景三:被删除元素在非叶子节点,子节点丰满
    在这里插入图片描述
  • 场景四:被删除元素在叶子节点,兄弟节点不丰满

在这里插入图片描述

最后来看一个 B 树的示例图:
B 树


B+ 树是在 B树的基础上,做的更进一步的优化,它的特征如下:

  1. 有 m 个子树的中间节点包含有 m 个元素,每个元素不保存数据,只用来判断
  2. 叶子节点中包含了全部元素信息,及指向具体数据的指针,且叶子节点依元素自小而大的顺序链接

看一个 B+ 树的示意图:
B+ 树


MySQL 为什么使用 B+ 树而不是 B 树主要由预读策略导致:计算机存储分为两种:内存和外存,外存就是常说的磁盘

内存操作速度极快,外存磁盘数据基于机械运动。每次磁盘读取数据的时间分为寻道时间、旋转延迟和传输时间。其中主要花费时间再寻道和旋转延时上,传输时间可忽略不及。一般每次磁盘 IO 需要 9ms 左右时间,而每秒差不多能执行上亿次内存操作,也就是说:执行一次 I/O 的时间可以执行几十万条内存操作

考虑到磁盘 I/O 非常慢,操作系统提出局部预读来提高效率,也就是说每当读取某个地址的数据时,其相邻的数据很快也会被访问到,所以磁盘以页为单位读取数据,每次读取一页大小,一页大约 4K 或者 8K

而索引存储在磁盘中,想要更快更高效的查到数据,主要需减少的就是 IO 的次数,IO 次数越少,查询速度越高。B 树的每个节点的元素可以视为一次 I/O 读取,树的高度表示最多的 I/O 次数,因此树的高度越低,查询效率越高。

因此 B+ 树相比 B树 具有以下优点:

  1. 树更低:B+ 树的非叶子节点没有存储指向元素的具体指针,所需内存更小,树的高度更低
  2. 效率稳定:B+ 树每次查询总是从根到叶子节点,效率稳定,B 树查找的节点层数低时效率高,层数高时效率低
  3. 更适合范围查询:B+ 树叶子节点间存在指针,范围查找实际就是指针的遍历

至于红黑树就更不用说了,每个节点都包含两个子节点,树高度极高,查询效率肯定比不上 B+ 树和 B 树

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值