什么是索引?

面试的时候大家基本都回答,索引就像是字典的目录,通过定位的目录迅速的就能找到所对应的内容,这样回答可能比较片面。在我理解,索引是一种提高搜索效率散列存储的一种数据结构

为什么要使用索引?

在不使用索引的情况下,当一个表里面有上百万行数据的时候,查询某一条数据会导致扫描全表,一行数据一行数据的遍历,导致查询时间变长效率变低。而使用索引,我们知道索引是一种数据结构,如果以id作为索引字段,把id放在树上,那么就可以通过二分法快速的查询出来,提高效率。

mysql索引为什么使用B树或B+树

我们先从最简单的二分搜索树开始分析,层层递进。

二分搜索树

定义:

1.若它的左子树不为空,则左子树上所有结点的值均小于等于根结点的值;

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

3.它的左右子树均为二分查找树。

深入浅出mysql索引
但是我们知道二分搜索树的右子树均大于根结点,如果插入的数据递增会怎么样(类似自增id)?那会使二分搜索树变成一个链表的形式,这样跟查全表没有什么区别
深入浅出mysql索引

平衡二叉树

定义:
1,它或者是一颗空树,或者具有以下性质的二叉排序树:它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树

条件一:它必须是二叉查找树
条件二:每个节点的左子树和右子树的高度差至多为1
深入浅出mysql索引
深入浅出mysql索引

每个节点的组成结构:

首先我们先说一下树的每一个节点都存有什么东西,我们可以把一个节点当成一个磁盘块,索引是存在磁盘上面的,每一个节点磁盘块里面存了三块内容,我们以id作为索引为例:
第一部分存的是关键字(索引字段),如果id为10那么就存10
第二部分是数据区,数据区里面存的是数据引用,也就是说存的是这一条id为10 的数据在磁盘上面的地址
第三部分存的是指向子节点的引用

平衡二叉树会左旋右旋进行自我的平衡,这样的话就解决了,二分搜索树形成链表的问题了,那么为什么不使用它作为索引的数据结构?

原因一:太深了,平衡二叉树只有两路,存储大量数据会导致树的层级变深,我们知道一次遍历树的节点,就会把节点读取到磁盘上,每一次都是一次磁盘io的损耗,当层级越深,磁盘io开销很大

原因二:太少了,操作系统与磁盘io一次交互的数据量为一页,这里一页为4k,而mysql还不一样,一次io交互的数据为16k,但是平衡二叉树只有两路,存的数据很少,导致增加磁盘io

平衡多路查找树(B树)

定义:
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对应下图最后一层节点的空格子;
深入浅出mysql索引
1,b树能够存储多路,路数计算,(16*1024)/字段定义大小,所以索引字段定义越小,路数就越多,就能存越多的数据,树的层级就变低,搜索的速度就变快
2,因为关键字的个数是m-1,所以当我们进行插入,删除字段的时候,可能会产生节点的合并或断裂,也会产生系统开销,所以为什么索引不要建太多,要合适比较好

B+树

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

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

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

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

4,非叶子节点的子节点数=关键字数。

深入浅出mysql索引

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

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

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

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

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

相关文章: