为什么Mysql用B+树做索引而不用B-树或红黑树

B+树做索引而不用B-树

  • 那么Mysql如何衡量查询效率呢?– 磁盘IO次数。
  • 一般来说索引非常大,尤其是关系性数据库这种数据量大的索引能达到亿级别,所以为了减少内存的占用,索引也会被存储在磁盘上。

B-树/B+树的特点就是每层节点数目非常多,层数很少,目的就是为了减少磁盘IO次数,但是B-树的每个节点都有data域(指针),这无疑增大了节点大小,说白了增加了磁盘IO次数(磁盘IO一次读出的数据量大小是固定的,单个数据变大,每次读出的就少,IO次数增多,一次IO多耗时), 而B+树除了叶子节点其它节点并不存储数据,节点小,磁盘IO次数就少。

B+树的优点

优点一: B+树的磁盘读写代价更低:B+树只有叶节点存放数据,其余节点用来索引,而B-树是每个索引节点都会有Data域。

优点二: B+树带有顺序访问指针:B+树所有的Data域在叶子节点,并且所有叶子节点之间都有一个链指针。 这样遍历叶子节点就能获得全部数据,这样就能进行区间访问啦。在数据库中基于范围的查询是非常频繁的,而B树不支持这样的遍历操作。

优点三:B+树的查询效率更加稳定:由于非叶子节点并不是最终指向文件内容的节点,而只是叶子节点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。而B树因为非叶子节点也存在数据Data域,有可能在非叶子节点中就可获取数据并返回。

B+数带有顺序访问指针的优点

一般在数据库系统或文件系统中使用的B+Tree结构都在经典B+Tree的基础上进行了优化,增加了顺序访问指针。在B+Tree的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的B+Tree。做这个优化的目的是为了提高区间访问的性能,例如如果要查询key为从15到60的所有数据记录,当找到15后,只需顺着节点和指针顺序遍历就可以一次性访问到所有数据节点,极大提到了区间查询效率。

B树的优点

对于在内部节点的数据,可直接得到,不必根据叶子节点来定位

B+树做索引而不用红黑树

AVL 树(平衡二叉树)和红黑树(二叉查找树)基本都是存储在内存中才会使用的数据结构。

在大规模数据存储的时候,红黑树往往出现由于树的深度过大而造成磁盘IO读写过于频繁,进而导致效率低下的情况。

为什么会出现这样的情况?

我们知道要获取磁盘上数据,必须先通过磁盘移动臂移动到数据所在的柱面,然后找到指定盘面,接着旋转盘面找到数据所在的磁道,最后对数据进行读写。磁盘IO代价主要花费在查找所需的柱面上,树的深度过大会造成磁盘IO频繁读写。根据磁盘查找存取的次数往往由树的高度所决定,所以,只要我们通过某种较好的树结构减少树的结构尽量减少树的高度,B树可以有多个子女,从几十到上千,但是降低树的高度。

数据库设计者选择

数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。为了达到这个目的,在实际实现B-Tree还需要使用如下技巧:每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了一个node只需一次I/O。

B-Tree有许多变种,其中最常见的是B+Tree,例如MySQL就普遍使用B+Tree实现其索引结构。

磁盘和内存选择B树和红黑树的原因

B树优点
  1. B+树的高度要比红黑树小,有效减少了磁盘的随机访问
  2. B+树的数据节点相互临近,能够发挥磁盘顺序读取的优势(缓存)
  3. B+树的数据全部存于叶子结点,而其他节点产生的浪费在经济负担上能够接收,红黑树存储浪费小
红黑树优点
  1. 红黑树常用于存储内存中的有序数据,增删很快,B+树常用于文件系统和数据库索引,因为B树的子节点大于红黑树,红黑树只能有2个子节点,B树子节点大于2,子节点树多这一特点保证了存储相同大小的数据,树的高度更小,数据局部更加紧凑,而硬盘读取有局部加载的优化(紧凑的好处:把要读取数据和周围的数据一起预先读取),B树相邻数据物理上更加紧凑这一特点符合硬盘进行io优化的特性。
  2. B+树在B树基础上进一步将数据只存在叶子节点,非叶子节点不存值只存储值的指向,这使得单个节点能有更多子节点,除此之外将所有叶子节点(值存在叶子节点)放入链表中,使得数据更加紧凑有序,只需要链表(叶子节点)的一次遍历就能获取所有树上的值。

B+树这些特性适合用于数据库的索引,mysql底层数据结构就是B+树。

B树更适用于磁盘读取,红黑树更适用于内存读取

为什么Mysql用B+树做索引而不用B-树或红黑树

上一篇:C#引入SqlLite


下一篇:设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)