mysql联合索引B 树_B+树和Mysql索引详解

B+树总结

根据以下几篇文章总结的自己的心得,便于自己理解

B+树内部平衡详解

B+树存储原理

B+树存储

MySQL索引-B+树(看完你就明白了)

从B树、B+树、B*树谈到R 树

我们一般看到的B+树都如下图所示

ca0aadbe2b60b8423164a2df4adcf89c.png

看了很多文章因为都跟这个图类似。这里有几个问题:

1.为什么节点上的key值能是别的数字比如(6 29 66)吗?换句话说节点上的数值显示的哪几个有没有规律?

2.节点上的key值能不能比这个多。换句话说这个数量是不是固定的?

第一个问题:

因为我们知道想正常的二叉树他的根节点是由第一个插入的数值来决定的。后面插入的会根据和根节点相比较来决定左右分配。而平衡二叉树是会改变根节点的数值来使这个二叉树的左右分支的阶数相差不会超过一阶。所以B+数也是同理,他会通过自己内部的平衡,也就是插入的数值和数量来决定自己的根节点的数值和数量。

第二个问题:

通过第一个问题的解答,知道节点的数量是不固定的。但是其有一个返回。包括B+数的指针和叶子节点都有规律。这也是其内部来进行平衡的原理。

(1)根结点只有1个,分支数量范围[2,m]。m代表阶数

(2)除根以外的非叶子结点,每个结点包含分支数范围[[m/2], m],其中[m/2]表示取大于m/2的最小整数。

(3)所有非叶子节点的关键字数目等于它的分支数量。

(4)所有叶子节点都在同一层,且关键字数目范围是[[m/2],m],其中[m/2]表示取大于 m/2的最小整数。

(5)所有非叶子节点的关键字可以看成是索引部分,这些索引等于其子树(根结点)中的最大(或最小)关键字。例如一个非叶子节点包含信息:(n,AO,KO,A1,K1,…… Kn, An),其中 Ki为关键字,Ai为指向子树根结点的指针,n 表示关键字个数。即Ai所指子树中的关键字均小于或等于Ki,而Ai+1所指的关键字均大于Ki (i=1,2,……,n)。

(6)叶子节点包含全部关键字的信息(非叶子节点只包含索引),且叶子结点中的所有关键字依照大小顺序链接(所以一个B+树通常有两个头指针,一个是指向根节点的 root,另一个是指向最小关键字的sqt)。

内部平衡规律举例:

e60a04c593c06782f49e00f104c935ae.png

494048a192ad08142a33cca226b74ede.png

d673231d6ede76eed195e7efa78ce2ac.png

09ed310a5e210b0b1add365fd556fa88.png

(第一个链接里面有很多举例讲的很清楚)

2.Mysql索引

数据页与数据行

我们都知道,数据库数据是存在磁盘中的,不过真正处理数据是在内存中进行的。这就需要从硬盘上不断地把数据读到内存中,由于内存和磁盘速度差了好几个数量级,所以为了避免频繁交互带来的性能问题,mysql一次会多读取一些,是多少呢?读一页。一页有16KB,也就是说一次读取一般都是16KB的倍数。页是硬盘内存交互的基本单位。

7c4506e441d9fe5e1863adc05d8d887d.png

如上图所示,是一张数据页内部结构。一个16KB的页,内部存放着很多行,比如说那3条记录,除此之外,内部存放着两个特殊的记录,最小记录和最大记录。数据页内部记录之间是以单链表的形式存放的,头尾分别是那两个特殊的记录。在内存中有很多页,页和页之间是用双链表连接的。这样方便快速定位到数据在哪一页上。

003e4f01c46e33ca7b5ac56965019092.png

B+树的优点:

磁盘IO次数更低:

因为非叶子节点不保存其数据,每个节点可以保存的关键字更多了,MySQL每页保存的数据更多,所以减少了磁盘IO

查询效率更稳定:

每次查找过程就是从根节点到叶子节点的过程,几乎是稳定O(n)。B+树只需要去遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作或者说效率太低。

B+树更利于对数据库的扫描:

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

例如:

搜索id > 10的数据,找到10对应的叶子节点之后,直接通过链指针Q直接往右边统计即可。如果是B树,找到节点10之后,需要回到上层做中序遍历。

PS:

真实数据的B+树是真扁平的,深度很小的。B+树高度一般为1-3层,它就能满足千万级的数据存储。

聚簇索引

一般创建表的时候都会创建一个自增的主键id,如果自己没有创建系统也会默认帮我们创建一个隐藏的列。而innoDB中的B+树的叶子几点key值就是存放的id,而数据区存放的就是一行数据。这种存储模式就是聚簇索引。

一般根据id作为条件直接查询的时候,就可以直接从数据区取出一行数据而不用二次会标查询,所以效率很快。

二级索引

也就是根据别的字段创建的索引,此时会有一个新的B+树,而这个B+树key值存放的是这个字段的数值,而且也是按升序排列。

aa0efee80d86b93f9b8dd20c2089358f.png

如图所示,当查询时会先找到这个条件值所在的位置,然后拿到数据区里面的id值,然后在根据id值二次回表到聚簇索引查询一行数据

联合索引

比如给name+age创建联合索引,此时的数据区就是先按name进行升序,在按age进行升序,这个其实跟二级索引差不多。主要是注意索引的失效。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值