MySQL索引B+Tree原理

1.索引概念

索引是为了加速对表中数据行的检索而创建的一种分散存储的数据结构

2. 特点:

  1. 索引能极大的减少存储引擎需要扫描的数据量
  2. 索引可以把随机IO变成顺序IO
  3. 索引可以帮助我们在进行 分组、 排序等操作时,避免使用临时表

3 MYSQL的储存结构B+Tree的由来

背景知识点:Mysql的的每一个磁盘块(页、节点)都是固定大小的(16k),这个也是可以设置的

3.1 二叉树Binary search Tree

每一个磁盘块存储一个关键字(索引),如图所示:


MySQL索引B+Tree原理_第1张图片
二叉树

3.2.平衡二叉树 Balanced binary search tree

MySQL索引B+Tree原理_第2张图片
平衡二叉树

前面两个二叉树可以总结如下:

  1. 它太深了
    数据处的(高)深度决定着他的IO 操作次数,IO 操作耗时大,如上图如果要找到索引3需要经过三次IO。
  2. 它太小了
    每一个磁盘块 (节点/ 页) 保存的数据量太小 了(一个节点只有一个关键字和相应的数据,信息太少)
    没有很好的利用操作磁盘IO 的数据 交换 特性(一个磁盘16k,估计只用了1k,多次IO后获取到的无用信息太多)
    也没有利用好磁盘IO 的预 读能力(操作系统定义的空间局部性原理 ),从而带来频繁的IO。(在你读取当前节点时,它认为你要读取接下来的节点,帮你提前读)

3.3.多路平衡查找树 B-Tree

这里多路指的一个磁盘块(节点)有n个子节点,那么当前节点就保存了n-1个关键字的数据。下面这个图就是三路,一个节点保存了两个关键字的信息和三个节点的引用。
这样相比二叉树,每一个节点的信息也就可以存储更多的信息了,如图:


MySQL索引B+Tree原理_第3张图片
二叉树

3.4.加强版多路平衡查找树 B+Tree

相比B-Tree树,做了如下改变。磁盘块不在保存关键字的信息(索引对应数据的地址引用),而只是保存在叶子节点上。并且采用左闭合的方式。

MySQL索引B+Tree原理_第4张图片
image.png

非叶子节点(比如5,28,65)只是一个key(索引),实际的数据存在叶子节点上(5,8,9)才是真正的数据或指向真实数据的指针

两个B树 对比总结:

B+Tree采用左闭右开的关键字搜索区间
B+Tree非叶节点不保存数据相关信息,只保存关键字和子节点的引用
B+Tree关键字对应的数据保存在叶子节点上
B+Tree叶子节点上的数据时顺序排序的,并且相邻接点具有顺序引用的关系

3.5. 选择 B+Tree 的优点

B+树是B- 树的变种(PLUS 版)多路绝对平衡查找树,他拥有B- 树的优势
B+树扫库、表能力更强
B+树的磁盘读写能力更强
B+树的排序能力更强

4 应用

4.1 为什么说B+树比B树更适合数据库索引?

1、 B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。

2、B+树的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

3、由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。

PS:我在知乎上看到有人是这样说的,我感觉说的也挺有道理的:

他们认为数据库索引采用B+树的主要原因是:B树在提高了IO性能的同时并没有解决元素遍历的我效率低下的问题,正是为了解决这个问题,B+树应用而生。B+树只需要去遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作或者说效率太低。

4.2 B/B+树性能分析

n个节点的平衡二叉树的高度为H(即logn),而n个节点的B/B+树的高度为logt((n+1)/2)+1;
若要作为内存中的查找表,B树却不一定比平衡二叉树好,尤其当m较大时更是如此。因为查找操作CPU的时间在B-树上是O(mlogtn)=O(lgn(m/lgt)),而m/lgt>1;所以m较大时O(mlogtn)比平衡二叉树的操作时间大得多。因此在内存中使用B树必须取较小的m。(通常取最小值m=3,此时B-树中每个内部结点可以有2或3个孩子,这种3阶的B-树称为2-3树)。

总结

数据库使用B+树肯定是为了提升查找效率。

但是具体如何提升查找效率呢?

查找数据,最简单的方式是顺序查找。但是对于几十万上百万,甚至上亿的数据库查询就很慢了。

所以要对查找的方式进行优化,熟悉的二分查找,二叉树可以把速度提升到O(log(n,2)),查询的瓶颈在于树的深度,最坏的情况要查找到二叉树的最深层,由于,每查找深一层,就要访问更深一层的索引文件。在多达数G的索引文件中,这将是很大的开销。所以,尽量把数据结构设计的更为‘矮胖’一点就可以减少访问的层数。在众多的解决方案中,B-/B+树很好的适合。B-树定义具体可以查阅,简而言之就是中间节点可以多余两个子节点,而且中间的元素可以是一个域。相比B-树,B+树的父节点也必须存在于子节点中,是其中最大或者最小元素,B+树的节点只存储索引key值,具体信息的地址存在于叶子节点的地址中。这就使以页为单位的索引中可以存放更多的节点。减少更多的I/O支出。因此,B+树成为了数据库比较优秀的数据结构,MySQL中MyIsAM和InnoDB都是采用的B+树结构。不同的是前者是非聚集索引,后者主键是聚集索引,所谓聚集索引是物理地址连续存放的索引,在取区间的时候,查找速度非常快,但同样的,插入的速度也会受到影响而降低。聚集索引的物理位置使用链表来进行存储。

你可能感兴趣的:(MySQL索引B+Tree原理)