为什么MySQL数据库要用B+树存储索引

二叉树,平衡二叉树,红黑树,B树,B+树理解

 

数据库中的数据一般是放在磁盘里面,存取数据的时候就要访问磁盘,
物理访问过程:盘片旋转,磁臂移动 两个过程。盘片旋转到指定位置之后,移动磁臂开始进行数据的存取。

那么存取数据的时间(快慢)主要是在哪部分消耗呢?主要就是定位过程消耗的。
所以:考虑到提高存取数据的速率,实际上就是减少磁盘定位(I/O操作)的次数。

来举个例子。来顺序查找


查找5的时候,从头到尾的遍历,一共需要定位5次。不用再赘述,显然这样的顺序查找是最低效的。

为了提高效率,来二叉树
二叉树的规范我就不说了,

 

一共6个数,无论查找哪个数,最多也就定位3次。
嗯,既然二叉树这么方便,那大家都用二叉树好了。额,其实图一那种情况,也算是二叉树,那算是一种情况。如果无法保证提高效率的稳定性,那这种结构还是不好。
(在这里记录一个知识点)
先序,中序,后序遍历。说一点就好,这里的先中后,说的是根节点。

为了提升稳定性,来平衡二叉树
平衡二叉树用平衡因子差值来判断是否平衡,并旋转二叉树。平衡因子:左右子树高度差。平衡二叉树里平衡因子不能超过1,否则旋转。
长叹一口气,这样稳定了吧?
稳定是稳定,但是为了二叉树的稳定,牺牲了一些更重要的东西——时间。
当新增删除数据导致的旋转二叉树时,很耗时间的!
所有的操作的目的都是为了节省时间,提高效率。这样操作舍本逐末了。但也不是丝毫没有可取之处。
使用场景:新增删除数据少,查找数据多的应用场景可以。

在稳定性的基础上,再优化一下,减少一下旋转次数吧,来红黑树
红黑树(Java中TreeMap)特性:
1、每个节点要么是红色,要么是黑色。
2、根节点必须是黑色。
3、红色节点不能连续(也即是,红色节点的孩子和父亲都不能是红色)。
4、对于每个节点,从该点至null(树尾端)的任何路径,都含有相同个数的黑色节点。

 

红黑树旋转的关键逻辑是:确保任何一个节点的左右子树的高度差不会超过二者中较低那个的一倍。举例:节点A,左子树高度X,右子树高度Y, X-Y<=min(X,Y);
所以当 X-Y > min(X,Y),然后开始旋转,红黑树的旋转逻辑请看这位大神博客。https://www.cnblogs.com/CarpenterLee/p/5503882.html ,很清晰了。

红黑树已经稳成这样了,满足吗?不满足,还可以更稳。来B树
学习B树的时候我曾看到这样的定义。

子女?元素?孩子?值域?关键字?儿子?
OMG,虽然最后我理解了博主们的意思,但是这也太费劲儿了。所以按自己的理解,写一个试试看。

前提:M阶B树
三种结点:根结点,中间结点,叶子结点
孩子:指一个结点下的子结点
关键字:结点中的值

1、根结点孩子数量:[2,M]
2、中间结点孩子数量:[ceil(M/2), M]
3、根结点和中间结点的关键字数量:他们的孩子数量 -1

4、一个结点当中:指向孩子指针和关键字的位置关系是:(指针1) 关键字A (指针2) 关键字B (指针3)
   每个关键字的值 > 左指针 指向的孩子树里结点中的关键字
   每个关键字的值 < 右指针 指向的孩子树里结点中的关键字

5、叶子结点位于同一层
6、结点中的关键字从小到大排列
7、结点中关键字不重复

 


图片和定义都祭出之后,B树对于红黑树的优势很明显了,最明显的就是B树一个结点存放了多个关键字。将在磁盘中的定位操作移到了结点中的关键字大小比较

 

B树是很可以,但并不是对所有场景都友好。来B+树
先说说什么场景B树不友好,范围查询:比如要找上图中E->O,两个字母之间的所有字母。那B树的逻辑就是中序查找到E,继续中序查找到O,然后拿出来字母。
那么B+树对于这种场景就很简单了。来先说一说B+树基本的东西,说完也就知道了为什么用B+树范围查找比B树简单了。

1、根节点和中间结点 的 孩子数量 = 关键字数量
2、根节点和中间结点 的 关键字 是 关键字对应子树中所有关键字的最大值,同时也存在于子树中
3、根节点和中间结点 只做索引,不包含数据指针以及数据

4、叶子结点包含所有数据,并按照从小到大顺序排列
5、叶子结点用指针连在一起

所以,对于范围查询:比如查找3-8之间的数字,B+树的做法是直接在叶子结点上的有序链表上遍历即可。
而且,B+树比B树的查找更加稳定,因为每次找到都会到叶子结点。
那为什么B+树每次都会到叶子结点?B树每次到哪里?
B树上的关键字代表一个索引key,和它同时存在的是key所指向的内容在内存中实际的存储位置。如果遍历到了某个关键字,那么就根据指针去真实数据的存储位置。
B+树上的 非叶子节点 关键字只代表索引key,叶子结点上存储真实数据 或者 指向真实数据位置 的指针。

二叉树是一种树形结构:

特点是与每个节点关联的子节点至多有两个(可为0,1,2

每个节点的子节点有关联位置关系

定义:

二叉树是节点的有限集合,该集合或为空集,或由一个根元素和两棵不相交的二叉树组成(递归定义)

二叉树的两棵子树分别称为它的左子树和右子树

 

二叉树的5种基本形态:

 

空二叉树

只有根节点

只有左子树,右子树为空

只有右子树,左子树为空

左右子树都不为空

 

 

满的和完全的二叉树:

满二叉树:树中每个分支节点(非叶节点)都有两棵非空子树

完全二叉树:除最下两层外,其余节点度数都是2,如果最下面的节点不满,则所有空位都在右边,左边没有空位,如下图

 

 

 

扩充二叉树(由已有非空二叉树生成的一种二叉树):

是原二叉树的最小节点扩充,使原树中所有节点的度数都变成2

 

二叉树的性质:

性质1. 非空二叉树第 i 层上至多有 2i 个结点(i ≥ 0

性质2. 高度为 k 的二叉树至多有 2k-1 个结点(k ≥ 0)

性质3. 对任何非空二叉树 T,若其叶结点个数为 n0,度数为 2 的结点

个数为 n2,则n0 = n2 + 1

性质4. n 个结点的完全二叉树的高度 k = ⎡log2(n+1)⎤

性质5. 满二叉树里的叶结点比分支结点多一个

二叉树的数据结构

基本操作

创建二叉树

一棵二叉树或为空(用 None 表示),或是两棵已有二叉树和要存在树根结点的一项数据,构造起的根结点代表构造出的二叉树:

BiTree(dat, left, right)

判断树空:is_empty(bitree)

访问操作,访问二叉树的组成成分:

访问二叉树的根结点数据元素:data()

取得一棵二叉树的左右子树:right(),left()

 

 

case ... esac 与其他语言中的 switch ... case 语句类似,是一种多分枝选择结构。

 

case 语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令。case语句格式如下:

 

​   case工作方式如上所示。取值后面必须为关键字 in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。;; 与其他语言中的 break 类似,意思是跳到整个 case 语句的最后。

 

​   取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令

 

1. 树

 

2. 红黑树

3. 红黑树。。。

4. 红黑树的定义和如何实现的就不要说了,说说红黑树的优点

5. 二叉排序树【左边比根节点小,后边比根节点大】

6. 二叉排序树的退化

 

 7. 红黑树

8.因为:

 

 

 

 9.B树

 

 

 

 

 

 10. 文件系统用B树,不用红黑树或别的呢

 

 

 

 

 

 

 

 

 

 11. B+ 树

 

 

 

 

如果是多条的话,B 树需要做局部的中序遍历,可能要跨层访问。

而 B+ 树由于所有数据都在叶子结点,不用跨层,同时由于有链表结构,只需要找到首尾,通过链表就能把所有数据取出来了。

 

 

 


 

 

回到现场

 

HAHAHA

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值