一、背景

一般说MySQL的索引,都清楚其索引主要以B+树为主,此外还有Hash、RTree、FullText。本文简要说明一下MySQL的B+Tree索引,以及和其相关的二叉树、平衡二叉树、B-Tree,相关的知识网上很多,为了方便自己更快、清楚的了解,文本聚合一些内容以及个人的一些理解。

二、二叉查找树(BST)

(1)概念:
二叉查找树是基于二分查找法来提高数据查找速度的二叉树的数据结构;关于二分查找法的时间复杂度可以看 时间复杂度 O(log n) 意味着什么?。(2)特点
二叉查找树是采用二分查找法把数据按规则组装成一个树形结构的数据,减少无关数据的检索,提升了数据检索的速度;二叉树的数据结构有以下规则:

  • (1)非叶子节点只能允许最多两个子节点存在。
  • (2)每一个非叶子节点数据分布规则为左边的子节点小当前节点的值,右边的子节点大于当前节点的值;即二叉查找树的特点就是任何节点的左子节点的键值都小于当前节点的键值,右子节点的键值都大于当前节点的键值。
    顶端的节点称为根节点,没有子节点的节点我们称之为叶节点。以下图中的圆为二叉查找树的节点,节点中存储了键(key)和数据(data)。

查找结点值的方法就是二分查找法:查找次数就是树的高度。二叉查找树可以任意地构造 如果向一方倾斜的二叉树是不平衡的,查询效率就低了,二叉查找树变成了一个链表。如下图:

在上面的2张图中,查找键值为17的数据,第一张图里需要3次IO,第2张图里需要7次IO。原因是二叉查找树变得不平衡了,也就是高度太高了,从而导致查找效率的不稳定。为了解决这个问题,需要保证二叉查找树一直保持平衡,就需要用到平衡二叉树了。


本群免费分享学习资料(C/C++,Linux,golang,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,ffmpeg,TCP/IP,协程,DPDK,嵌入式)等。更多的学习资料请加qqun:1106675687。

三、平衡二叉树(AVL)

在满足二叉查找树特性的基础上,如不是空树,任何一个结点的左子树与右子树都是平衡二叉树,并且高度之差的绝对值不超过 1。 类似于:

关于平衡二叉树的可以看 什么是平衡二叉树(AVL)该文章说明,平衡二叉树相比于二叉查找树来说,查找效率更稳定,总体的查找速度也更快。需要注意的是平衡二叉树是每个节点只存储一个键值和数据的。

四、B树(B-Tree)

(1)概念:
B树和平衡二叉树不同,B树属于多叉树又名平衡多路查找树(查找路径不只两个),数据库索引里大量使用者B-Tree和B+Tree的数据结构。(2)特点:

  • (1)排序方式:所有节点关键字是按递增次序排列,并遵循左小右大原则;
  • (2)子节点数:非叶节点的子节点数>1,且<=M
    ,且M>=2,空树除外(注:M阶代表一个树节点最多有多少个查找路径,M=M路,当M=2则是2叉树,M=3则是3叉);
  • (3)关键字数:枝节点的关键字数量大于等于ceil(M/2)-1个且小于等于M-1个(注:ceil()是个朝正无穷方向取整的函数
    如ceil(1.1)结果为2);
  • (4)所有叶子节点均在同一层、叶子节点除了包含了关键字还包含了数据;

最后我们用一个图和一个实际的例子来理解B树(这里为了理解方便我就直接用实际字母的大小来排列C>B>A)

图中可以看到BTree的单个节点可以存储多个键值和数据的平衡树。和平衡二叉树相比:
比如要存储海量的数据,因为(平衡)二叉树的每个节点只存储一个键值和数据的,二叉树的节点将会非常多,高度也会及其高,当查找数据时也会进行很多次磁盘IO,查找的效率将会极低,大致的二叉树结构如下:

为了解决平衡二叉树的这个弊端,需要一种单个节点可以存储多个键值和数据的平衡树(BTree):

从上图可以看出,B树相对于平衡二叉树,每个节点存储了更多的键值(key)和数据(data),并且每个节点拥有更多的子节点,子节点的个数一般称为阶,上述图中的B树为3阶B树,高度也会很低。 基于这个特性,B树查找数据读取磁盘的次数将会很少,数据的查找效率也会比平衡二叉树高很多。假如我们要查找id=28的用户信息,那么我们在上图B树中查找的流程如下:

  1. 先找到根节点也就是页1,判断28在键值17和35之间,我们那么我们根据页1中的指针p2找到页3。
  2. 将28和页3中的键值相比较,28在26和30之间,我们根据页3中的指针p2找到页8。
  3. 将28和页8中的键值相比较,发现有匹配的键值28,键值28对应的用户信息为(28,bv)。

区别:B树相对于平衡二叉树的不同是:每个节点包含的关键字增多了,特别是在B树应用到数据库中的时候,数据库充分利用了磁盘块的原理(磁盘数据存储是采用块的形式存储的,每个块的大小为4K,每次IO进行数据读取时,同一个磁盘块的数据可以一次性读取出来)把节点大小限制和充分使用在磁盘快大小范围;把树的节点关键字增多后树的层级比原来的二叉树少了,减少数据查找的次数和复杂度。
相同数量的key在B-Tree中生成的节点要远远少于二叉树中的节点,相差的节点数量就等同于磁盘IO的次数。这样到达一定数量后,性能的差异就显现出来了。

五、B+树(B+Tree)

(1)概念
B+树是B树的一个进化,相对于B树来说B+树更充分的利用了节点的空间,让查询速度更加稳定,其速度完全接近于二分法查找。结构如下:

为什么说B+树查找的效率要比B树更高、更稳定;我们先看看两者的区别:1.B+树的非叶子节点不保存数据,只进行数据索引(关键字记录的指针),这样使得B+树每个非叶子节点所能保存的关键字大大增加;2.B+树叶子节点保存了父节点的所有关键字记录的指针,所有数据地址必须要到叶子节点才能获取到。所以每次数据查询的次数都一样;3.B+树叶子节点的关键字从小到大有序排列,左边结尾数据都会保存右边节点开始数据的指针;4.B+树非叶子节点的子节点数=关键字数;(2)特点:
1、B+树的层级更少:相较于B树,B+每个非叶子节点存储的关键字数更多,树的层级更少所以查询数据更快;
2、B+树查询速度更稳定:B+所有关键字数据地址都存在叶子节点上,所以每次查找的次数都相同所以查询速度要比B树更稳定;
3、B+树天然具备排序功能:B+树所有的叶子节点数据构成了一个有序链表,在查询大小区间的数据时候更方便,数据紧密性很高,缓存的命中率也会比B树高。
4、B+树全节点遍历更快:B+树遍历整棵树只需要遍历所有的叶子节点即可,而不需要像B树一样需要对每一层进行遍历,这有利于数据库做全表扫描。
B树相对于B+树的优点是:如果经常访问的数据离根节点很近,而B树的非叶子节点本身存有关键字其数据的地址,所以这种数据检索的时候会要比B+树快。根据上图我们来看下B+树和B树有什么不同:

  1. B+Tree 非叶子节点上是不存储数据的,仅存储键值,数据存储在同一层的叶节点,而B-Tree节点中不仅存储键值,也会存储数据。之所以这么做是因为在数据库中页的大小是固定的,innodb中页的默认大小是16KB。如果不存储数据,那么就会存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的IO次数有会再次减少,数据查询的效率也会更快。另外,B+Tree的阶数是等于键值的数量的,如果B+Tree一个节点可以存储1000个键值,那么3层B+树可以存储1000×1000×1000=10亿个数据。一般根节点是常驻内存的,所以一般我们查找10亿数据,只需要2次磁盘IO。
  2. 因为B+Tree索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。而B-Tree 因为数据分散在各个节点,要实现这一点是很不容易的。

B+Tree 中各个页之间是通过双向链表连接的,叶子节点中的数据是通过单向链表连接的。
其实上面的B-Tree也可以对各个节点加上链表。其实这些不是它们之前的区别,是因为在mysql的innodb存储引擎中,索引就是这样存储的。也就是说上图中的B+Tree索引就是innodb中B+Tree索引真正的实现方式,准确的说应该是聚集索引。
通过上图可以看到,在innodb中,数据页之间通过双向链表连接以及叶子节点中数据之间通过单向链表连接的方式可以找到表中所有的数据。
注意:MyISAM中的B+树索引实现与innodb中的略有不同。在MyISAM中,B+树索引的叶子节点并不存储数据,而是存储数据的文件地址。

六、总结

B+Tree 结构是从二叉查找树,平衡二叉树和B-Tree这三种数据结构演化来的,他们之前的区别上面已经介绍过,现在大致的总结下,如下:
1,二叉查找树是基于二分查找法来提高数据查找速度的二叉树的数据结构,减少无关数据的检索,提升了数据检索的速度。非叶子节点只能允许最多两个子节点存在,每一个非叶子节点数据分布规则为左边的子节点小当前节点的值,右边的子节点大于当前节点的值,每个节点只存储一个键值和数据的。
2,平衡二叉树满足二叉查找树特性的基础上,如不是空树,任何一个结点的左子树与右子树都是平衡二叉树,并且高度之差的绝对值不超过 1。
3,B-TreeB和平衡二叉树不同,B-Tree属于多叉树又名平衡多路查找树, B-Tree相对于平衡二叉树,每个节点存储了更多的键值(key)和数据(data),并且每个节点拥有更多的子节点。
4,B+Tree和B-Tree不同,B+Tree在非叶子节点上,不保存数据,只存储指针,能存储更多的键值,相应的树的阶数(节点的子节点树)就会更大,树就会更矮更胖,如此一来我们查找数据进行磁盘的IO次数有会再次减少,数据查询的效率也会更快。并且B+树索引的所有数据均存储在叶子节点,而且数据是按照顺序排列的。那么B+树使得范围查找,排序查找,分组查找以及去重查找变得异常简单。


首先恭喜您,能够认真的阅读到这里,如果对部分理解不太明白,建议先将文章收藏起来,然后对不清楚的知识点进行查阅,然后在进行阅读,相应你会有更深的认知。如果您喜欢这篇文章,就点个赞或者【关注我】吧!!

带父节点的平衡二叉树_深入理解(二叉树、平衡二叉树、B-Tree、B+Tree )的区别相关推荐

  1. 带父节点的平衡二叉树_数据结构(八)平衡二叉树

    该来的总会来,平衡二叉树果然又来了.... 出现背景 前文已经研究过普通的二叉树, 为什么要用二叉树呢?因为二叉树的结构可以实现二分法查找的效果. 你比如前文介绍的满二叉树:如下图所示, 如果你想要查 ...

  2. 带父节点的平衡二叉树_平衡二叉树 通俗易懂

    平衡二叉树(AVL) 阅读之前请先了解 二叉搜索树 平衡二叉树定义:任意节点的子树的高度差都小于等于 1 1. 为什么使用「平衡二叉树」 二叉树能提高查询的效率 O(logn),但是当你插入 {1,2 ...

  3. 带父节点的平衡二叉树_学习数据结构--第四章:树与二叉树(平衡二叉树)

    第四章:树与二叉树(平衡二叉树) 1.平衡二叉树 平衡二叉树:AVL,任意结点的平衡因子的绝对值不超过一. 平衡因子:左子树高度 - 右子树高度 如上图二叉树,是否是平衡二叉树? 可以把所有结点的平衡 ...

  4. 带哨兵节点的链_【算法导论】10.2不带哨兵节点和带哨兵节点的双向链表

    不带哨兵节点的双向链表即一般的双向链表,有一个头指针指向第一个节点,每个节点有key值和两个指针next和pre,分别指向前后相邻的节点,头结点的pre=NULL,尾节点的next=NULL,比较明了 ...

  5. 子节点随父节点高度改变_完全二叉树的子节点数

    如果让你数一下一棵普通二叉树有多少个节点,这很简单,只要在二叉树的遍历框架上加一点代码就行了. 但是,如果给你一棵完全二叉树,让你计算它的节点个数,你会不会?算法的时间复杂度是多少? 这个算法的时间复 ...

  6. 带哨兵节点的链_限流降级神器-哨兵(sentinel)的资源调用链原理分析

    点击上方 Yoon丶徒手摘星 ,选择 置顶或者星标技术干货每日送达! 我们已经知道了sentinel实现限流降级的原理,其核心就是一堆Slot组成的调用链. 这里大概的介绍下每种Slot的功能职责:N ...

  7. 最大堆和最小堆和平衡二叉树_最小堆二叉树

    最大堆和最小堆和平衡二叉树 A Min Heap Binary Tree is a Binary Tree where the root node has the minimum key in the ...

  8. 带父节点的平衡二叉树_平衡二叉树的左右旋以及双旋转的图文详解

    高度平衡的搜索二叉树 一棵平衡树,或是空树,或是具有以下性质的二叉搜索树:左子树和右子树都是AVL树,且左右子树的高度之差的绝对值不超过1. 该二叉树,根结点的右子树高度为3,左子树高度为2.结点上方 ...

  9. 带父节点的平衡二叉树_Python算法系列—深度优先遍历算法【二叉树】

    一.什么是深度优先遍历 深度优先遍历算法是经典的图论算法.从某个节点v出发开始进行搜索.不断搜索直到该节点所有的边都被遍历完,当节点v所有的边都被遍历完以后,深度优先遍历算法则需要回溯到v以前驱节点来 ...

最新文章

  1. 【通用CSS模板】移动端H5页面统一样式.css
  2. Database项目中关于Procedure sp_refreshsqlmodule_internal的错误
  3. 企业网络推广之中如何对网页设计提出新的色彩搭配原理?
  4. 初探Java设计模式1:创建型模式(工厂,单例等)
  5. Entity Framework Core 懒加载
  6. java ThreadLocal理解和使用
  7. git push 提示:更新被拒绝,因为您当前分支的最新提交落后于其对应的远程分支。的解决办法
  8. QT入门学习(一):什么是QT
  9. 自媒体行业的发展和前景
  10. linux 飞信机器人 下载,飞信机器人FXRobot 's | CN-SEC 中文网
  11. Python代码格式化工具autopep8安装及使用极简版
  12. 量子计算机 霍金,科学家正在使用量子粒子窥视黑洞内部
  13. 从一个简单的数学题来说说偷换概念引发的催眠效应
  14. 机器学习第四章之逻辑回归模型
  15. moses 编译_Moses 训练步骤
  16. 猿人学试题(非常简单js混淆、雪碧图、样式干扰 css加密、js混淆源码乱码、js混淆动态cookie、访问逻辑)
  17. 大数相乘 (模板)
  18. matlab costas环,基于Matlab的Costas环仿真设计
  19. 业务指标基础分析(excel)--python实现
  20. Bisulfite Sequencing

热门文章

  1. LeetCode 221. 最大正方形(DP)
  2. atoi函数_每日一道 LeetCode (50):字符串转换整数 (atoi)
  3. 人类附身机器人获得永生_脑机接口先驱尼古莱利斯:人类无法实现数字永生
  4. mysql 线性表_线性表之顺序存储,基本操作
  5. linux java 共享内存_Linux进程间通信之共享内存
  6. python新手练习项目_适合Python 新手的5大练手项目,你练了么?
  7. 【RippleNet】(一)preprocessor.py【未完】
  8. 论文浅尝 - JWS2020 | FEEL: 实体抽取和链接的集成框架
  9. 论文浅尝 | 基于知识库的类型实体和关系的联合抽取
  10. 领域应用 | 人工智能+知识图谱:如何规整海量金融大数据?