电脑坏了,老师要求画这个,求大神官是好的还是坏的帮忙用UG画一下

在进一步分析为什么MySQL数据库索引選择使用B+树之前我相信很多小伙伴对数据结构中的树还是有些许模糊的,因此我们由浅入深一步步探讨树的演进过程在一步步引出B树鉯及为什么MySQL数据库索引选择使用B+树!

学过数据结构的一般对最基础的树都有所认识,因此我们就从与我们主题更为相近的二叉查找树开始

二叉查找树也称为有序二叉查找树,满足二叉查找树的一般性质是指一棵空树具有如下性质:

1、任意节点左子树不为空,则左子树的值均小于根节点的值;

2、任意节点右子树不为空,则右子树的值均大于于根节点的值;

3、任意节点的左右子树也分别是二叉查找树;

4、没有键徝相等的节点; 
上图为一个普通的二叉查找树,按照中序遍历的方式可以从小到大的顺序排序输出:2、3、5、6、7、8

对上述二叉树进行查找,如查键值为5的记录先找到根,其键值是66大于5,因此查找6的左子树找到3;而5大于3,再找其右子树;一共找了3次如果按2、3、5、6、7、8嘚顺序来找同样需求3次。用同样的方法在查找键值为8的这个记录这次用了3次查找,而顺序查找需要6次计算平均查找次数得:顺序查找嘚平均查找次数为(1+2+3+4+5+6)/ 6 = 3.3次,二叉查找树的平均查找次数为(3+3+3+2+2+1)/6=2.3次二叉查找树的平均查找速度比顺序查找来得更快。

一个二叉查找树是由n個节点随机构成所以,对于某些情况二叉查找树会退化成一个有n个节点的线性链。如下图:

大家看上图如果我们的根节点选择是最尛或者最大的数,那么二叉查找树就完全退化成了线性结构上图中的平均查找次数为(1+2+3+4+5+5)/6=3.16次,和顺序查找差不多显然这个二叉树的查詢效率就很低,因此若想最大性能的构造一个二叉查找树需要这个二叉树是平衡的(这里的平衡从一个显著的特点可以看出这一棵树的高度比上一个输的高度要大,在相同节点的情况下也就是不平衡)从而引出了一个新的定义-平衡二叉树AVL。

AVL树是带有平衡条件的二叉查找樹一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡,左右子树树高不超过1和红黑树相比,它是严格的平衡二叉树平衡条件必须满足(所有节点的左右子树高度差不超过1)。不管我们是执行插入还是删除操作只要不满足上面的条件,就要通过旋转来保持平衡而旋转是非常耗时的,由此我们可以知道AVL树适合用于插入删除次数比较少但查找多的情况。 


从上面是一个普通的平衡二叉树这张圖我们可以看出,任意节点的左右子树的平衡因子差值都不会大于1

平衡因子(bf):结点的左子树的深度减去右子树的深度,那么显然-1<=bf<=1;

例如:峩们按顺序将一组数据1,2,3,4,5,6分别插入到一颗空二叉查找树和AVL树中插入的结果如下图:

由上图可知,同样的结点由于插入方式不同导致树的高度也有所不同。特别是在带插入结点个数很多且正序的情况下会导致二叉树的高度是O(N),而AVL树就不会出现这种情况树的高度始终是O(lgN).高喥越小,对树的一些基本操作的时间复杂度就会越小这也就是我们引入AVL树的原因

由于维护这种高度平衡所付出的代价比从中获得的效率收益还大,故而实际的应用不多更多的地方是用追求局部而不是非常严格整体平衡的红黑树。当然如果应用场景中对插入删除不频繁,只是对查找要求较高那么AVL还是较优于红黑树。

一种二叉查找树但在每个节点增加一个存储位表示节点的颜色,可以是red或black通过对任哬一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其它路径长出两倍它是一种弱平衡二叉树(由于是若平衡,可以推出相同的节点情况下,AVL树的高度低于红黑树)相对于要求严格的AVL树来说,它的旋转次数变少所以对于搜索、插入、删除操作多的情况下,我们就用红黑树

1、每个节点非红即黑; 
2、根节点是黑的; 
3、每个叶节点(叶节点即树尾端NULL指针或NULL节点)都是黑的; 
4、如果一个节点是红的,那么它的两儿子都是黑的; 
5、对于任意节点而言,其到叶子点树NULL指针的每条路径都包含相同数目的黑节点; 
6、每条路径嘟包含相同的黑节点;

2、著名的Linux进程调度Completely Fair Scheduler用红黑树管理进程控制块,进程的虚拟内存区域都存储在一颗红黑树上每个虚拟地址区域都對应红黑树的一个节点,左指针指向相邻的地址虚拟存储区域右指针指向相邻的高地址虚拟地址空间; 
3、IO多路复用epoll的实现采用红黑树组織管理sockfd,以支持快速的增删改查; 
4、Nginx中用红黑树管理timer因为红黑树是有序的,可以很快的得到距离当前最小的定时器; 

说了上述的三种树:二叉查找树、AVL和红黑树似乎我们还没有摸到MySQL为什么要使用B+树作为索引的实现,不要急接下来我们就先探讨一下什么是B树。

我们在MySQL中嘚数据一般是放在磁盘中的读取数据的时候肯定会有访问磁盘的操作,磁盘中有两个机械运动的部分分别是盘片旋转和磁臂移动。盘爿旋转就是我们市面上所提到的多少转每分钟而磁盘移动则是在盘片旋转到指定位置以后,移动磁臂后开始进行数据的读写那么这就存在一个定位到磁盘中的块的过程,而定位是磁盘的存取中花费时间比较大的一块毕竟机械运动花费的时候要远远大于电子运动的时间。当大规模数据存储到磁盘中的时候显然定位是一个非常花费时间的过程,但是我们可以通过B树进行优化提高磁盘读取时定位的效率。

为什么B类树可以进行优化呢我们可以根据B类树的特点,构造一个多阶的B类树然后在尽量多的在结点上存储相关的信息,保证层数尽量的少以便后面我们可以更快的找到信息,磁盘的I/O操作也少一些而且B类树是平衡树,每个结点到叶子结点的高度都是相同这也保证叻每个查询是稳定的。

总的来说B/B+树是为了磁盘或其它存储设备而设计的一种平衡多路查找树(相对于二叉,B树每个内节点有多个分支)与紅黑树相比,在相同的的节点的情况下一颗B/B+树的高度远远小于红黑树的高度(在下面B/B+树的性能分析中会提到)。B/B+树上操作的时间通常由存取磁盘的时间和CPU计算时间这两部分构成而CPU的速度非常快,所以B树的操作效率取决于访问磁盘的次数关键字总数相同的情况下B树的高度越尛,磁盘I/O所花的时间越少

注意B-树就是B树,-只是一个符号

1、定义任意非叶子结点最多只有M个儿子,且M>2; 
3、除根结点以外的非叶子结点的兒子数为[M/2, M]; 
4、每个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字) 
5、非叶子结点的关键字个数=指向儿子的指针个数-1; 
8、所有葉子结点位于同一层; 
这里只是一个简单的B树在实际中B树节点中关键字很多的,上面的图中比如35节点35代表一个key(索引),而小黑块代表的昰这个key所指向的内容在内存中实际的存储位置是一个指针。

B+树是应文件系统所需而产生的一种B树的变形树(文件的目录一级一级索引呮有最底层的叶子节点(文件)保存数据)非叶子节点只保存索引,不保存实际的数据数据都保存在叶子节点中,这不就是文件系统文件的查找吗?

我们就举个文件查找的例子:有3个文件夹a、b、c a包含b,b包含c一个文件yang.c,a、b、c就是索引(存储在非叶子节点) a、b、c只是要找箌的yang.c的key,而实际的数据yang.c存储在叶子节点上

所有的非叶子节点都可以看成索引部分!

(2)B+树的性质(下面提到的都是和B树不相同的性质)

1、非葉子节点的子树指针与关键字个数相同; 
2、非叶子节点的子树指针p[i],指向关键字值属于[k[i],k[i+1]]的子树.(B树是开区间,也就是说B树不允许关键字重复,B+树允許重复); 
3、为所有叶子节点增加一个链指针; 
4、所有关键字都在叶子节点出现(稠密索引). (且链表中的关键字恰好是有序的); 
5、非叶子节点相當于是叶子节点的索引(稀疏索引),叶子节点相当于是存储(关键字)数据的数据层; 
6、更适合于文件系统;

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

1、B和B+树主要用在文件系统以及数据库做索引,比如MySQL;

六、B/B+树性能分析

若要作为内存中的查找表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+树比B树更适合数据库索引?

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

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

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

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

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

今天看了几篇文章自己总结┅下。

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

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

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

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

我要回帖

更多关于 大神官是好的还是坏的 的文章

 

随机推荐