mysql b 树 b树,浅谈B树,B+树,B*树及分析MySQL的索引

标签:

树的基本概念

根:树的顶端结点

兄弟:具有同一个双亲(Parent)的孩子(Child)之间互称为兄弟(Sibling)。

祖先:结点的祖先(Ancestor)是从根(Root)到该结点所经分支(Branch)上的所有结点。

叶子(终端结点):没有孩子的结点(也就是度为0的结点)称为叶子(Leaf)或终端结点。

度:结点所拥有的子树个数称为结点的度(Degree)。

边:一个结点和另一个结点之间的连接被称之为边(Edge)。

层次:结点的层次(Level)从根(Root)开始定义起,根为第0层,根的孩子为第1层。

路径:连接结点和其后代的结点之间的(结点,边)的序列。

结点的高度:结点的高度是该结点和某个叶子之间存在的最长路径上的边的个数。

树的高度:树的高度是其根结点的高度。

结点的深度:结点的深度是从树的根结点到该结点的边的个数。(注:树的深度指的是树中结点的最大层次。)

森林:森林是n(>=0)棵互不相交的树的集合。

二叉树(Binary Search Tree)

定义:每个结点至多拥有两棵子树(即二叉树中不存在度大于2的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒。

二叉树的性质:

若二叉树的层次从0开始,则在二叉树的第i层至多有2^i个结点(i>=0)。

高度为k的二叉树最多有2^(k+1) - 1个结点(k>=-1)。 (空树的高度为-1)高度为k的二叉树最多有2^(k+1) - 1个结点(k>=-1)。 (空树的高度为-1)

对任何一棵二叉树,如果其叶子结点(度为0)数为m, 度为2的结点数为n, 则m = n + 1。对任何一棵二叉树,如果其叶子结点(度为0)数为m, 度为2的结点数为n, 则m = n + 1。

B树

B树的结构要求:

1)根节点至少有两个子节点

2)每个节点有M-1个key,并且以升序排列

3)位于M-1和M key的子节点的值位于M-1 和M key对应的Value之间

4)其它节点至少有M/2个子节点

5)所有叶子节点都在同一层

4628c3ced8a1cfe7bd59582defcedfec.png

查询

以上图为例:若查询的数值为5:

第一次磁盘IO:在内存中定位(与17、35比较),比17小,左子树;

第二次磁盘IO:在内存中定位(与8、12比较),比8小,左子树;

第三次磁盘IO:在内存中定位(与3、5比较),找到5,终止。

整个过程中:比较的次数并不比二叉查找树少,尤其适当某一节点中的数据很多时,但是磁盘IO的次数却是大大减少。比较是在内存中进行的,相比于磁盘IO的速度,比较的耗时几乎可以忽略。所以当树的高度足够低的话,就可以极大的提高效率。相比之下,节点中的元素多点也没关系,仅仅是多了几次内存交互而已,只要不超过磁盘页的大小即可。

B+树

B+树是B树的升级版本,有着比B树更高的查询效率,也是一种多路搜索树:

其定义基本与B-树同,除了:

非叶子结点的子树指针与关键字个数相同;

非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树(B-树是开区间);

为所有叶子结点增加一个链指针;

所有关键字都在叶子结点出现;

05a833e8caec75086bbd4cabb69e03e0.png

查找

首先,B+树的查找和B树一样,类似于二叉查找树。起始于根节点,自顶向下遍历树,选择其分离值在要查找值的任意一边的子指针。在节点内部典型的使用是二分查找来确定这个位置。

不同的是:

B+树中间节点没有卫星数据(索引元素所指向的数据记录),只有索引,而B树每个结点中的每个关键字都有卫星数据;这就意味着同样的大小的磁盘页可以容纳更多节点元素,在相同的数据量下,B+树更加“矮胖”,IO操作更少。

B树的卫星数据:

1c61189056743f2e776635b2a708ec7e.png

B+树的卫星数据:

b8bedde8491194fe16892c4caae00054.png

需要补充的是,在数据库的聚集索引(Clustered Index)中,叶子节点直接包含卫星数据。在非聚集索引(NonClustered Index)中,叶子节点带有指向卫星数据的指针。

因为卫星数据的不同,导致查询过程也不同;B树的查找只需找到匹配元素即可,最好情况下查找到根节点,最坏情况下查找到叶子结点,所说性能很不稳定,而B+树每次必须查找到叶子结点,性能稳定

在范围查询方面,B+树的优势更加明显:B树的范围查找需要不断依赖中序遍历。首先二分查找到范围下限,在不断通过中序遍历,知道查找到范围的上限即可。整个过程比较耗时。

而B+树的范围查找则简单了许多。首先通过二分查找,找到范围下限,然后同过叶子结点的链表顺序遍历,直至找到上限即可,整个过程简单许多,效率也比较高。

例如:同样查找范围[3-11],两者的查询过程如下:

B树的查找过程:

baf7c8ddb5b158f899e38aadbd8436d5.png

B+树的查找过程:

73469e7664d0486bdb0c878fafe41e76.png

B*树

接下来要说明的就是B树,B树是对B+树进行的又一次的升级。在B+树的非根和非叶子结点再增加指向兄弟的指针;

eb6e348c5f51cf01ca9f0389d4eacf6f.png

在B+树基础上,为非叶子结点也增加链表指针,将结点的最低利用率从1/2提高到2/3;

在这比如说当你进行插入节点的时候,它首先是放到兄弟节点里面。如果兄弟节点满了的话,进行分裂的时候从兄弟节点和这个节点各取出1/3,放入新建的节点当中,这样也就实现了空间利用率从1/2到1/3。

MySQL的索引

什么是索引?

首先索引引入的目的是为了快速查询以及更新表中的数据。索引是一种存储在硬盘上的,对数据库表中一列或多个列进行排序的数据结构。

索引是一个单独存储在磁盘上的数据库结构,它们包含着对数据表里所有记录的引用指针,使用索引可以提高数据库特定数据的查询速度.索引时在存储引擎中实现的,因此每种存储引擎的索引不一定完全相同,并且每种存储引擎也不一定支持所有索引类型.

为什么不用二叉搜索树

一句话:因为磁盘IO问题。之前说过,索引是存储在磁盘上的,对数据库表中一列或多列进行排序的数据结构。数据库中的数据可能很大,在大量的数据存储在磁盘上时。计算机无法一次性将数据全部加载进内存。而是通过逐一加载每一磁盘页。而加载磁盘页对应着索引树的节点。那么一次查找所经历的索引树的深度对应着磁盘IO交互的次数。如果采取二叉树结构,那么显而易见,可能导致遍历的深度太大导致磁盘IO交互的次数太多。而相较于内存查询,磁盘IO才是影响查询以及更新表中数据的关键。那么由二叉树这样的瘦长结构自然容易联想到如何将它变的矮胖。这样做虽然没有降低比较次数,由于深度的降低,可以极大的减少磁盘IO次数。从而可以提升查询以及更新数据的性能。

B树相较于二叉搜索树的中序遍历,没有减少多少,甚至一点都没有减少,不过降低了磁盘IO的次数。对于提高索引查询以及更新数据来说。这就足够了,毕竟磁盘IO才是影响性能的关键。

b+树相比于b树的查询优势:

b+树的中间节点不保存数据,所以磁盘页能容纳更多节点元素,更“矮胖”;

b+树查询必须查找到叶子节点,b树只要匹配到即可不用管元素位置,因此b+树查找更稳定(并不慢);

所有叶子节点形成有序链表,便于范围查询,b+树只需遍历叶子节点链表即可,b树却需要重复地中序遍历。

为什么说B±tree比B 树更适合实际应用中操作系统的文件索引和数据库索引?

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

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

数据库索引采用B+树而不是B树的主要原因:B+树只要遍历叶子节点就可以实现整棵树的遍历,而且在数据库中基于范围的查询是非常频繁的,而B树只能中序遍历所有节点,效率太低。

文件索引和数据库索引为什么使用B+树?

文件与数据库都是需要较大的存储,也就是说,它们都不可能全部存储在内存中,故需要存储到磁盘上。而所谓索引,则为了数据的快速定位与查找,那么索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数,因此B+树相比B树更为合适。数据库系统巧妙利用了局部性原理与磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入,而红黑树这种结构,高度明显要深的多,并且由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性。最重要的是,B+树还有一个最大的好处:方便扫库。B树必须用中序遍历的方法按序扫库,而B+树直接从叶子结点挨个扫一遍就完了,B+树支持range-query非常方便,而B树不支持,这是数据库选用B+树的最主要原因

标签:

来源: https://blog.csdn.net/ZLZ2017/article/details/86016105

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值