Mysql索引为啥要用B+树?

原创
2018/01/05 17:25
阅读数 7.4K

     我们都知道Mysql索引用的B+树作为数据结构,但是为啥呢?王侯将相宁有种乎,树有这么多,凭啥就是你B+树,我AVL树,红黑树,Trie树等表示不服。

     不服先等着,我们看看树旋转。树旋转是在二叉树中的一种子树调整操作, 每一次旋转并不影响对该二叉树进行中序遍历的结果。

  • AVL树

     AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树

     性质:任一节点的左子树深度和右子树深度相差不超过1

                              

               (非AVL树)                                               (前面的树转化成的AVL树)       

      时间复杂度:

       插入:O(1)。只需要一次或者两次旋转来维持平衡。

       删除:O(logN)。最差的情况就要每层的节点进行树旋转,所以时间复杂度为O(logN)。

       查询:O(logN)。

  • 红黑树

     红黑树是每个节点都带有颜色属性的二叉查找树,颜色为红色和黑色。

     性质:

  1. 节点是红色或黑色。
  2.  根是黑色。
  3. 所有nill节点都是黑色。
  4. 从每个叶子到根的所有路径上不能有两个连续的红色节点。
  5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。

      注意性质4导致了路径不能有两个毗连的红色节点,最短的可能路径都是黑色节点,最长的可能路径有交替的红色和黑色节点。因为根据性质5所有最长的路径都有相同数目的黑色节点,这就表明了没有路径能多于任何其他路径的两倍长。      

                                     

                                                    ( 一颗普通的红黑树)

       时间复杂度:

       插入:O(1)。在一些插入情形,红黑树最多只要两次旋转就能保持其性质。但是在只需要更改颜色就能保持颜色的情形下,红黑树可能需要logN次变换颜色才能保持其性质。但是变换颜色的需要的开销远远小于树旋转的开销,所以算作O(1)。

       删除:O(1)。 同插入,最多三次旋转就能保持其性质。

       插入:O(logN)。 

  • Trie树 

       trie,又称前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。一般情况下,不是所有的节点都有对应的值,只有叶子节点和部分内部节点所对应的键才有相关的值。

                               

                                                (一课普通的Trie树)

       trie树常用于搜索提示。如当输入一个网址,可以自动搜索出可能的选择。当没有完全匹配的搜索结果,可以返回前缀最相似的可能。

       介绍完3位重量级选手,如果我们想自己设计mysql的索引会选用什么数据结构呢?trie树死在了开始,无疑AVL树在查询方面是最出色的,但是在删除的时候可能会引起噩梦,这样看来好像是红黑树最适合咯,虽然他牺牲了一部分查询性能,但是使删除性能在大部分情况保持了常数的时间复杂度。但是,有一个最重要的问题是,mysql的数据是放在外部存储的,也就是说磁盘IO才是性能瓶颈的关键,所以我们需要的是减少树的深度,所以我们需要更多分叉的树 ,还需要更适合磁盘操作特性的数据结构。

       B+树是为磁盘或其他直接存取的辅助存储设备而设计的一种数据结构。mysql为什么选取B+树,本质上是因为mysql数据是存放在外部存储的。

  • B+树

       未见其字,先闻其图。(实在是不好定义)

                    

                                                 (一颗普通的B+树)

     性质(m叉B+树):

  1. 树中每个结点至多有m个孩子。
  2. 除根结点和叶子结点外,其它每个结点至少有[m/2]个孩子。
  3. 若根结点不是叶子结点,则至少有2个孩子。
  4. 所有叶子结点都出现在同一层。
  5. 每个非终端节点中包含n个关键字信息:(A0,K1,A1,K2,A2,......,Kn,An)。其中,Ki (i=1...n)为关键字,且关键字按顺序排序Ki < K(i-1)。Ai为指向子树根的接点,且指针A(i-1)指向子树种所有结点的关键字均小于Ki,但都大于K(i-1)。关键字的个数n必须满足: [m/2]-1 <= n <= m-1

       当然还有一种性质是说n个关键字只有n个孩子,这里就不讨论了。

    优势:

  1. 只有叶子节点才记录数据,非叶子节点只包含索引;所有的非终端节点(内部节点)并不存储数据信息,而是保存其叶子节点的最小值作为索引。 这样,一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。

  2. 能够提供稳定高效的范围扫描(range-query)功能;这也是为什么数据库和操作系统中的文件系统通常会采用b+树作为数据索引的原因,这个特点主要因为所有叶子节点相互连接,并且叶子节点本身依关键字的大小自小而大顺序链接。

      

展开阅读全文
打赏
0
0 收藏
分享
加载中
感觉图画的有点问题,fan out 应该是少了一个
2019/09/26 10:39
回复
举报
更多评论
打赏
1 评论
0 收藏
0
分享
返回顶部
顶部