Mysql原理解析 - 索引文件的存储结构

前言

局部性原理

在这里插入图片描述

磁盘预读

磁盘预读(预读的长度一般为页(page)的整数倍) – 页是存储器的逻辑块,操作系统往往将主存和磁盘存储区分割为连续的大小
相等的块,每个存储块称为一页(在许多操作系统中,页大小通常为4k),
主存和磁盘以页为单位交换数据。

索引是什么?

索引是帮助 MySQL 高效获取数据的数据结构
▪ 索引存储在文件系统中
▪ 索引的文件存储形式与存储引擎有关
▪ 索引文件的结构
– 哈希表
– 二叉树
– AVL树(平衡二叉搜索树)
– 红黑树
– B树
– B+树

1. MSQL为什么索引选择B+树?

在进一步分析为什么MySQL数据库索引选择使用B+树之前
我相信很多小伙伴对数据结构中的树还是有些许模糊的
因此我们由浅入深一步步探讨树的演进过程
再一步步引出B树以及为什么MySQL数据库索引选择使用B+树!

学过数据结构的一般对最基础的树都有所认识,因此我们就从与我们主题更为相近的二叉查找树开始。

1.1 哈希表hash

简介:

哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地方
如果我想要获取“按”字详细信息,我肯定会去根据拼音an去查找 拼音索引(当然也可以是偏旁索引)
我们首先去查an在字典的位置,查了一下得到“安”,结果如下。
这过程就是键码映射,在公式里面,就是通过key去查找f(key)。其中,按就是关键字(key),f()就是字典索引,也就是哈希函数
查到的页码4就是哈希值。

在这里插入图片描述

局限性:

哈希表可以完成索引的存储,每次在添加索引的时候需要计算指定列的hash值,取横运算后计算出下标,将元素插入下标位置即可
适合场景:
       等值查询
       表中的数据是无序数据(范围查找的时候比较浪费时间,需要挨个进行遍历操作)
在企业中多数的查询时是范围查询而不是等值查询
所以此时hash表不合适范围查询
hash表在使用的时候,需要将全部的数据加载到内存,比较耗费内存的空间,也不是很合适
如果我们要查的是“按”,而不是“安,但是他们的拼音都是一样的。也就是通过关键字按和关键字安可以映射到一样的字典页码4的位置
这就是哈希冲突(也叫哈希碰撞)

1.2 二叉树

简介:

二叉查找树也称为有序二叉查找树,满足二叉查找树的一般性质,是指一棵空树具有如下性质:


1、任意节点左子树不为空,则左子树的值均小于根节点的值;
2、任意节点右子树不为空,则右子树的值均大于于根节点的值;
3、任意节点的左右子树也分别是二叉查找树;
4、没有键值相等的节点;

在这里插入图片描述

上图为一个普通的二叉查找树,按照中序遍历的方式可以从小到大的顺序排序输出:2、3、5、6、7、8。
对上述二叉树进行查找,如查键值为5的记录,先找到根,其键值是6,6大于5,因此查找6的左子树找到3;
而5大于3,再找其右子树;一共找了3次。如果按2、3、5、6、7、8的顺序来找同样需求3次。
用同样的方法在查找键值为8的这个记录,这次用了3次查找,而顺序查找需要6次。
计算平均查找次数得:
       顺序查找的平均查找次数为(1+2+3+4+5+6)/ 6 = 3.3次,
       二叉查找树的平均查找次数为(3+3+3+2+2+1)/6=2.3次。
二叉查找树的平均查找速度比顺序查找来得更快。

局限性:

一个二叉查找树是由n个节点随机构成,所以,对于某些情况,二叉查找树会退化成一个有n个节点的线性链。
大家看上图,如果我们的根节点选择是最小或者最大的数,那么二叉查找树就完全退化成了线性结构。
上图中的平均查找次数为(1+2+3+4+5+5)/6=3.16次,和顺序查找差不多。显然这个二叉树的查询效率就很低
因此若想最大性能的构造一个二叉查找树,需要这个二叉树是平衡的
(这里的平衡从一个显著的特点可以看出这一棵树的高度比上一个输的高度要大,在相同节点的情况下也就是不平衡)
从而引出了一个新的定义- 平衡二叉树AVL。

1.3 AVL树

简介:

AVL树是带有平衡条件的二叉查找树,一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡,左右子树树高不超过1,
和红黑树相比,它是严格的平衡二叉树,平衡条件必须满足(所有节点的左右子树高度差不超过1)。
不管我们是执行插入还是删除操作,只要不满足上面的条件,就要通过1到N次的旋转来保持平衡。
而旋转是非常耗时的,严重影响插入的性能。由此我们可以知道AVL树适合用于插入删除次数比较少,但查找多的情况。
上图是一个普通的平衡二叉树,这张图我们可以看出,任意节点的左右子树的平衡因子差值都不会大于1。

局限性:

AVL树是一颗严格意义上的平衡树,最高子树跟最低子树高度之差不能超过1,
因此在进行元素插入的时候,会进行1到N次的旋转,而旋转严重影响插入的性能。
当然,如果应用场景中对插入删除不频繁,只是对查找要求较高,那么AVL还是较优于红黑树。

1.4 红黑树

简介:

红黑树是基于AVL树的一个升级,损失了部分查询的性能,来提升插入的性能,在红黑树中最低子树跟最高子树之差小于2倍即可,
在插入的时候,不需要进行N多次的旋转操作,而且还加入了变色的特性,来满足插入和查询性能的平衡。
它是一种二叉查找树,但在每个节点增加一个存储位表示节点的颜色,可以是red或black。
通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其它路径长出两倍。
它是一种弱平衡二叉树(由于是若平衡,可以推出,相同的节点情况下,AVL树的高度低于红黑树),
相对于要求严格的AVL树来说,它的旋转次数变少,所以对于搜索、插入、删除操作多的情况下,我们就用红黑树。
树的深度无法控制,插入教据的性能还是不够完美。

性质:

1、每个节点非红即黑;
2、根节点是黑的;
3、每个叶节点(叶节点即树尾端NULL指针或NULL节点)都是黑的;
4、如果一个节点是红的,那么它的两儿子都是黑的;
5、对于任意节点而言,其到叶子点树NULL指针的每条路径都包含相同数目的黑节点;
6、每条路径都包含相同的黑节点;

在这里插入图片描述

应用

1、广泛用于C++的STL中,Map和Set都是用红黑树实现的;
2、著名的Linux进程调度Completely Fair Scheduler,用红黑树管理进程控制块,进程的虚拟内存区域都存储在一颗红黑树上,每个虚拟地址区域都对应红黑树的一个节点,左指针指向相邻的地址虚拟存储区域,右指针指向相邻的高地址虚拟地址空间;
3、IO多路复用epoll的实现采用红黑树组织管理sockfd,以支持快速的增删改查;
4、Nginx中用红黑树管理timer,因为红黑树是有序的,可以很快的得到距离当前最小的定时器;
5、Java中TreeMap的实现;

1.5 总结

上述的哈希表与三种树(二叉查找树、AVL和红黑树)
相信大家已经知道了MySQL为什么要使用B+树作为索引的实现了叭

哈希表,二叉树及其N多的变种都不能支撑索引,原因是树的深度无法控制(深度过深而造成io次数变多)或者插入数据的性能比较低
解决办法:多叉树

2. B树/B+树

2.1 B树特点:

1、所有键值分布在整颗树中
2、搜索有可能在非叶子结点结束,在关键字全集内做一次查找,性能逼近二分查找
3、每个节点最多拥有m个子树
4、根节点至少有2个子树
5、分支节点至少拥有m/2颗子树(除根节点和叶子节点外都是分支节点)
6、所有叶子节点都在同一层、每个节点最多可以有m-1个key,并且以升序排列

在这里插入图片描述

局限性:

实例图说明:
每个节点占用一个磁盘块(每个假设4k),一个节点上有两个升序排序的关键字和三个指向子树根节点的指针,指针存储的是子节点所在磁盘块的地址。两个关键词划分成的三个范围域对应三个指针指向的子树的数据的范围域。以根节点为例,关键字为 16 和 34,P1 指针指向的子树的数据范围为小于 16,P2 指针指向的子树的数据范围为 16~34,P3 指针指向的子树的数据范围为大于 34。
查找关键字过程:
1、根据根节点找到磁盘块 1,读入内存。【磁盘 I/O 操作第 1 次】
2、比较关键字 28 在区间(16,34),找到磁盘块 1 的指针 P2。
3、根据 P2 指针找到磁盘块 3,读入内存。【磁盘 I/O 操作第 2 次】
4、比较关键字 28 在区间(25,31),找到磁盘块 3 的指针 P2。
5、根据 P2 指针找到磁盘块 8,读入内存。【磁盘 I/O 操作第 3 次】
6、在磁盘块 8 中的关键字列表中找到关键字 28。
缺点:

1、每个节点都有key,同时也包含data,而每个页存储空间是有限的,如果data比较大的话会导致每个节点存储的key数量变小
2、当存储的数据量很大的时候会导致深度较大,增大查询时磁盘io次数,进而影响查询性能

2.2 mysql索引数据结构 – B+树

B+Tree是在BTree的基础之上做的一种优化,变化如下:
1、B+Tree每个节点可以包含更多的节点,这个做的原因有两个:
        第一个原因是为了降低树的高度,
        第二个原因是将数据范围变为多个区间,区间越多,数据检索越快
2、非叶子节点存储key,叶子节点存储key和数据
3、叶子节点两两指针相互连接(符合磁盘的预读特性),顺序查询性能更高

注意:在B+Tree上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。因此可以对 B+Tree 进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。

在这里插入图片描述
下一篇:有InnoDB和MyISAM两种引擎,对B+树数据增删改的详细介绍

猜你喜欢

转载自blog.csdn.net/ws13575291650/article/details/113778002