MySQL学习(五)---->B+树索引

二叉树是每个节点最多有两个子节点的树。

二叉查找树又叫二叉搜索树,
它或者是一棵空树,或者是具有下列性质的二叉树:
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

一、平衡二叉树

  • 概念

平衡二叉树是基于二分法的策略提高数据的查找速度的二叉树的数据结构;

  • 特点:

平衡二叉树是采用二分法思维把数据按规则组装成一个树形结构的数据,用这个树形结构的数据减少无关数据的检索,大大的提升了数据检索的速度;平衡二叉树的数据结构组装过程有以下规则:

(1)非叶子节点只能允许最多两个子节点存在。

(2)每一个非叶子节点数据分布规则为左边的子节点小当前节点的值,右边的子节点大于当前节点的值(这里值是基于自己的算法规则而定的,比如hash值);

平衡树的层级结构:因为平衡二叉树查询性能和树的层级(h高度)成反比,h值越小查询越快、为了保证树的结构左右两端数据大致平衡降低二叉树的查询难度一般会采用一种算法机制实现节点数据结构的平衡,实现了这种算法的有比如Treap、红黑树,使用平衡二叉树能保证数据的左右两边的节点层级相差不会大于1.,通过这样避免树形结构由于删除增加变成线性链表影响查询效率,保证数据平衡的情况下查找数据的速度近于二分法查找;

常见的二叉树平衡方法有: LL(左旋转)、LR(左右双旋转)、RR(右旋转)、RL(右左双旋转)

总结平衡二叉树特点:

(1)非叶子节点最多拥有两个子节点;

(2)非叶子节值大于左边子节点、小于右边子节点;

(3)树的左右两边的层级数相差不会大于1;

(4)没有值相等重复的节点;

二、B树(B-tree)

注意:之前有看到有很多文章把B树和B-tree理解成了两种不同类别的树,其实这两个是同一种树;

  • 概念:

B树和平衡二叉树稍有不同的是B树属于多叉树又名平衡多路查找树(查找路径不只两个),数据库索引技术里大量使用者B树和B+树的数据结构,让我们来看看他有什么特点;

  • 规则:

(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)所有叶子节点均在同一层、叶子节点除了包含了关键字和关键字记录的指针外也有指向其子节点的指针只不过其指针地址都为null对应下图最后一层节点的空格子;

m阶B树:

⑴ 树中每个结点至多有m个孩子;

⑵ 除根结点和叶子结点外,其它每个结点至少有m/2个孩子;

⑶ 若根结点不是叶子结点,则至少有2个孩子;

⑷ 所有叶子结点都出现在同一层;

⑸ 有k个孩子的非终端结点恰好包含有k-1个关键字。

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

  • B树的查询流程:

如上图我要从上图中找到E字母,查找流程如下

(1)获取根节点的关键字进行比较,当前根节点关键字为M,E<M(26个字母顺序),所以往找到指向左边的子节点(二分法规则,左小右大,左边放小于当前节点值的子节点、右边放大于当前节点值的子节点);

(2)拿到关键字D和G,D<E<G 所以直接找到D和G中间的节点;

(3)拿到E和F,因为E=E 所以直接返回关键字和指针信息(如果树结构里面没有包含所要查找的节点则返回null);

  • B树的插入节点流程

定义一个5阶树(平衡5路查找树;),现在我们要把3、8、31、11、23、29、50、28 这些数字构建出一个5阶树出来;

遵循规则:

(1)节点拆分规则:当前是要组成一个5路查找树,那么此时m=5,关键字数必须<=5-1(这里关键字数>4就要进行节点拆分);

(2)排序规则:满足节点本身比左边节点大,比右边节点小的排序规则;

先插入 3、8、31、11

 

再插入23、29

再插入50、28

  • B树节点的删除

规则:

(1)节点合并规则:当前是要组成一个5路查找树,那么此时m=5,关键字数必须大于等于ceil(5/2)(这里关键字数<2就要进行节点合并);

(2)满足节点本身比左边节点大,比右边节点小的排序规则;

(3)关键字数小于二时先从子节点取,子节点没有符合条件时就向向父节点取,取中间值往父节点放;

特点:

B树相对于平衡二叉树的不同是,每个节点包含的关键字增多了,特别是在B树应用到数据库中的时候,数据库充分利用了磁盘块的原理(磁盘数据存储是采用块的形式存储的,每个块的大小为4K,每次IO进行数据读取时,同一个磁盘块的数据可以一次性读取出来)把节点大小限制和充分使用在磁盘块大小范围;把树的节点关键字增多后树的层级比原来的二叉树少了,减少数据查找的次数和复杂度;

1、每个节点相当于磁盘块,这样一次性读取的数据就多了

2、每个节点由key和指针构成,两头都是指针,指针永远比key多一个,指针指向下一个节点或者null

三、B+树

  • 概念

  B+树是B树的一个升级版,相对于B树来说B+树更充分的利用了节点的空间,让查询速度更加稳定,其速度完全接近于二分法查找。为什么说B+树查找的效率要比B树更高、更稳定;我们先看看两者的区别

  • 规则

(1)B+跟B树不同B+树的非叶子节点不保存关键字记录的指针,只进行数据索引,这样使得B+树每个非叶子节点所能保存的关键字大大增加;

(2)B+树叶子节点保存了父节点的所有关键字记录的指针,所有数据地址必须要到叶子节点才能获取到。所以每次数据查询的次数都一样;

(3)B+树叶子节点的关键字从小到大有序排列,左边结尾数据都会保存右边节点开始数据的指针。

(4)非叶子节点的子节点数=关键字数(来源百度百科)(根据各种资料 这里有两种算法的实现方式,另一种为非叶节点的关键字数=子节点数-1(来源维基百科),虽然他们数据排列结构不一样,但其原理还是一样的Mysql 的B+树是用第一种方式实现);

.

(百度百科算法结构示意图)

(维基百科算法结构示意图)

  • 特点

1、B+树的层级更少:相较于B树B+每个非叶子节点存储的关键字数更多,树的层级更少所以查询数据更快;

2、B+树查询速度更稳定:B+所有关键字数据地址都存在叶子节点上,所以每次查找的次数都相同所以查询速度要比B树更稳定;

3、B+树天然具备排序功能:B+树所有的叶子节点数据构成了一个有序链表,在查询大小区间的数据时候更方便,数据紧密性很高,缓存的命中率也会比B树高。

4、B+树全节点遍历更快:B+树遍历整棵树只需要遍历所有的叶子节点即可,,而不需要像B树一样需要对每一层进行遍历,这有利于数据库做全表扫描。

B树相对于B+树的优点是,如果经常访问的数据离根节点很近,而B树非叶子节点本身存有关键字其数据的地址,所以这种数据检索的时候会要比B+树快。

InnoDB中的索引方案

  不论是存放用户记录的数据页,还是存放目录项记录的数据页,我们都把它们存放到B+树这个数据结构中了,所以我们也称这些数据页为节点。我们的实际用户记录其实都存放在B+树的最底层的节点上,这些节点也被称为叶子节点叶节点,其余用来存放目录项的节点称为非叶子节点或者内节点,其中B+树最上边的那个节点也称为根节点。B+树非叶子节点只存放索引。

1. 非叶子节点只存key不存数据

  B+树中,非叶子节点是不存储数据的,只存储key,这样每个页能够存储更多的key,使得树更胖更矮,所以读取磁盘次数更少。假如B+树一个节点可以存储 1000 个键值,那么 3 层 B+ 树可以存储 1000×1000×1000=10 亿个数据,一般根节点是常驻内存的,所以一般我们查找 10 亿数据,只需要 2 次磁盘 IO。

2. 所有数据都存在叶子节点

  所有的数据都存在叶子节点,所以数据是按顺序存储的,使得范围查找、排序查找更加方便。

3. B+树的页之间用双向链表连接,数据间用单项链表链接

  页之间有双向链表链接,使得扫描数据更加快捷。

聚集索引

  上面说的B+树在叶子节点存储数据,这样的索引实际上就是聚集索引,像MySQL里会默认根据主键创建的索引就是聚集索引,根据主键构建一棵B+树,主键所对应的值直接存在叶子节点中。

根据主键查找的意义图如下所示:

select * from user where id>=18 and id <40

InnoDB存储引擎中,聚集索引就是数据的存储方式(所有的用户记录都存储在了叶子节点),也就是所谓的索引即数据,数据即索引

非聚集索引

根据主键以外的字段创建的索引一般都是非聚集索引,非聚集索引也是用B+树构建的,他和聚集索引的唯一不同就是叶子节点中保存的值不是实际的值,而是主键值,找到主键值后再去聚集索引中查找。

举例:

有这样一张表,id是主键,我们在luckyNum字段上创建的非聚集索引。

select * from user where luckNum=33

根据非聚集索引查找过程示意图如下:

 

 

                                                    

 

 

posted @ 2023-03-15 16:11  donleo123  阅读(24)  评论(0编辑  收藏  举报