Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL B+树索引

浅谈Mysql使用B+树来实现索引的原因

作者:JL8

这篇文章,主要来探讨一下为什么Mysql使用B+树来实现索引,这里讨论的目标是Mysql的InnoDB存储引擎.可以想象一下,如果你是Mysql的开发人员,你会怎么去选择合适的数据结构呢,感兴趣的小伙伴跟着小编一起来探讨吧

从实际场景出发

任何数据结构都是为了解决特定问题而产生的,那么如果一个用户使用Mysql,通常会有哪些需求呢?我们可以很容易的想到最简单的需求:

用户肯定希望查询的性能越高越好,对于一个表来说,如果能直接通过索引来查询到数据,不必进行全表扫描,那就再好不过了.

选择合适的数据结构

这个时候,Mysql的开发人员就会为了解决用户的查询性能问题,开始选择合适的数据结构.能想到的备选方案可能有Hash,B Tree,B+ Tree这三种数据结构.

如果使用Hash作为索引的数据结构

Hash能提供O(1)的查询复杂度,对于类似于select * from t where id = 3这种等值匹配来说,性能相当的高,可以说无人能及.但是对于范围查询来说,Hash就有点捉襟见肘了,Hash没办法做到用O(1)的复杂度来进行范围查询,因为这点,Hash是不适合作为底层索引的实现的.

使用B Tree还是B+ Tree

那么可选的方案现在只剩下B Tree和B+ Tree.因为这两者的数据结构有点相似,所以在这两个数据结构之间进行选择时,最好是将两者放在一起对比,才能更清楚的知道哪种才是更好的数据结构,.

首先我们应该清楚B树是如何存储数据的.这里给出一张图片:

我们现在以聚簇索引来举例,图中的数字代表主键值,后面的*代表该位置是存放实际的行数据的.每个节点的左指针指向下一级的节点,并且左边指向的节点的主键值大小比上一级的小,右边指向的节点的主键值比上一级的大.B Tree的一个重要特点是在每一个节点都存储了完整的行数据.

B+ Tree存储数据的方式是这样的:

B+ Tree的重要特点是:

在图中的12这个节点中,后面是指向24这个节点的,在图中被省略了.

在这里,我们再强调一下B Tree和B+ Tree的重要区别:

理解了这两者的区别之后,我们来考虑一下针对实际场景,哪个数据结构才是更好的选择.首先,我们考虑一下等值查询,对于B Tree来说,从根节点的主键值开始进行比较,根据左小右大的特点,可以在某个层级定位到整行数据并返回.对于B+ Tree来说,也是从根节点开始进行比较,不过最终必须定位到叶子节点才能获取到需要的数据.所以在等值查询这个场景下,B Tree看起来比B+ Tree来得好.

那么考虑一下范围查询,比如B Tree来说,查询数据跟等值查询的模式差不多,只不过需要扫描到多个层级的节点.举个例子,如果在上图中寻找主键大于等于10且小于等于24的行数据.

我们可以从这个过程中看到,范围查询需要从根节点出发,然后可能要找到它的下一级节点,直到找到所有符合的数据.

对于B+ Tree来说,寻找主键大于等于10且小于等于24的行数据的流程是这样的:

实际上数据最终都是存储到磁盘上的,对于Mysql来说,数据是以页为单位来存储数据,通常为4KB,在上面的图中,我们可以理解成每一个大的长方形框是一个页,而每个页里面存放了很多节点,对于B Tree来说,每个页的节点都存放整行数据,对于B+ Tree来说,非叶子页的节点只存放id,也被称为索引页,而叶子节点存放整行数据.对于页的读取,就涉及到IO操作,要知道IO读取数据的速度比从内存读取数据要慢得多,通常读取页的时间在10ms左右.

以范围查询为例,我们从IO的角度来概括一下B Tree和B+ Tree的区别.对于B Tree而言,读取根节点需要一次IO操作,加载出页之后,当前页的数据可能只有部分符合要求,然后根据页的指针再进行IO操作,找到另外的页,整个过程需要更多的IO操作,并且因为每次读取的页并不是所有数据都满足要求,所以这种方式被称为随机IO.那么对于B+ Tree而言,也需要从根节点向下查询,这其中也涉及到随机IO,但定位到需要的叶子节点后,读取页时只需要根据链表来定位到下一个页,每次读取的页大概率都是符合要求的数据,这种方式被称为顺序IO.所以在范围查询中,B Tree需要更多的IO操作,这样就需要耗费更多的时间.如果对随机IO和顺序IO不是很理解,文末有个参考资料可以去看一下.

所以整体上来看,B+ Tree是更好的选择.

以上就是浅谈Mysql使用B+树来实现索引的原因的详细内容,更多关于MySQL B+树索引的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文