温故而知新,可以为师矣。看到一篇介绍B数和B减树的文章,这里记录一下。
众所周知,MySQL的索引使用了B+树的数据结构。那么为什么不用B树呢?
先看一下B树和B+树的区别。
先介绍一下二叉搜索树。
二叉搜索树的搜索,从根结点开始,如果查询的关键字与结点关键字相等,则该结点为查询的结点,如果查询关键字比结点关键字小,则进入左子树,反之则进入右子树;如果左子树为空或者右子树为空,则返回查找不到响应的关键字;
如果二叉搜索树的所有叶子结点的左右子树的树木保持一个平衡即左右子树个数大致相等的话,其搜索则更接近与二分查找;但是它相比连续内存空的二分查找的优点是:改变二叉搜索树的结构(添加或者删除)不需要大段的移动数据,甚至通常都是常数开销;
如下图:
红色字体代表插入数据,搜索二叉树在插入结点时,只要根据插入数据的大小查找出他应该插入的位置即可,然而当在一个有序数组插入一个数据的时候,需要查询出他的位置,然后将其添加,后面的数据索引加一,这样的一个完整操作,相比下来二叉树的优点很明显了。
但是,当一个二叉树经历多次删除操作后,他就可能变换结构,如下图:
右边也是一个搜索二叉树,只不过不在平衡了,他的搜索功能也变成了线性的,同样的关键字可能导致不同的树结构索引,所以,在使用搜索二叉树时,还要考虑尽可能让B树保持左图的结构,避免和右图类似,这也有事所谓的平衡问题了。
实际使用的二叉搜索树都是在原二叉搜索树的基础上加上平衡算法,即平衡二叉树;如何保持B树节点分布均匀的平衡算法就是平衡二叉树的关键所在,平衡算法是一种在二叉搜索树的插入和删除结点时的一种策略。即:在插入或删除的同时保持二叉搜索树的平衡。
B-树就是B树(可能有部分人会习惯上把B-树读为B减树,其实并不存在B减树,只是读法上的不同而已),B就是balanced,平衡的意思。B-树就是指的B树,特此说明一下。
维基百科对B树的定义为“在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据、对其进行排序并允许以O(log n)的时间复杂度运行进行查找、顺序读取、插入和删除的数据结构。B树,概括来说是一个节点可以拥有多于2个子节点的二叉查找树。与自平衡二叉查找树不同,B-树为系统最优化大块数据的读和写操作。B-tree算法减少定位记录时所经历的中间过程,从而加快存取速度。普遍运用在数据库和文件系统。”
B 树可以看作是对2-3查找树的一种扩展,即他允许每个节点有M-1个子节点。
下图是一个M=4 阶的B树:
M=4的B树
可以看到B树是2-3树的一种扩展,他允许一个节点有多于2个的元素。
B树的插入及平衡化操作和2-3树很相似,这里就不介绍了。下面是往B树中依次插入
6 10 4 14 5 11 15 3 2 12 1 7 8 8 6 3 6 21 5 15 15 6 32 23 45 65 7 8 6 5 4 的演示动画:
B+树是对B树的一种变形树,它与B树的差异在于:
如下图是一个B+树:
M=4的B+树
下图是B+树的建立过程:
B树:有序数组+平衡多叉树;
B+树:有序数组链表+平衡多叉树;
B+树的非叶子结点只包含导航信息,不包含实际的值,所有的叶子结点和相连的节点使用链表相连,便于区间查找和遍历。
B+ 树的优点在于:
但是B树也有优点,其优点在于,由于B树的每一个节点都包含key和value,因此经常访问的元素可能离根节点更近,因此访问也更迅速。下面是B 树和B+树的区别图:
B树和B+树的区别图
B树是B+树一种变形,它是在B+树的基础上,将索引层以指针连接起来,使搜索取值更加快捷。
如下图(M = 3)
但是B树又在B+树的基础上产生了一系列的变化,如下:
所以B*树相对于B+树,空间利用率上有所提高,查询速率也有所提高。
mysql中,只有Memory(Memory表只存在内存中,断电会消失,适用于临时表)存储引擎显示支持Hash索引,是Memory表的默认索引类型,尽管Memory表也可以使用B+Tree索引。Hash索引把数据以hash形式组织起来,因此当查找某一条记录的时候,速度非常快。但是因为hash结构,每个键只对应一个值,而且是散列的方式分布。所以它并不支持范围查找和排序等功能。
B+Tree是mysql使用最频繁的一个索引数据结构,是Inodb和Myisam存储引擎模式的索引类型。相对Hash索引,B+Tree在查找单条记录的速度比不上Hash索引,但是因为更适合排序等操作,所以它更受欢迎。毕竟不可能只对数据库进行单条记录的操作。
带顺序访问指针的B+Tree
B+Tree所有索引数据都在叶子节点上,并且增加了顺序访问指针,每个叶子节点都有指向相邻叶子节点的指针。
这样做是为了提高区间效率,例如查询key为从18到49的所有数据记录,当找到18后,只要顺着节点和指针顺序遍历就可以以此向访问到所有数据节点,极大提高了区间查询效率。
大大减少磁盘I/O读取
数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点需要一次I/O就可以完全载入。
最后:
1、 B+树的磁盘读写代价更低:B+树的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了。
2、B+树的查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
3、B+树更便于遍历:由于B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只需要扫一遍叶子结点即可,但是B树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫,所以B+树更加适合在区间查询的情况,所以通常B+树用于数据库索引。
4、B+树更适合基于范围的查询:B树在提高了IO性能的同时并没有解决元素遍历的我效率低下的问题,正是为了解决这个问题,B+树应用而生。B+树只需要去遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作或者说效率太低。
二叉搜索树:二叉树,每个结点只存储一个关键字且值大于左子树,小于右子树。
B(B-)树:多路搜索树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范围的子结点; 所有关键字在整颗树中出现,且只出现一次,非叶子结点可以命中;
https://www.jianshu.com/p/7ce804f97967
https://blog.csdn.net/A_zhangq/article/details/99662693
https://www.cnblogs.com/aspirant/p/9214485.html