什么是MySQL索引

什么是MySQL索引

前言

谈到MySQL索引,大家可能第一步想到的是,索引的定义,其次,就是它的用法,但是呢,我个人觉得,我们再学习MySQL之前呢,先要牢记一点。正确的创建合适的索引重要的事说三遍,正确的创建合适的索引正确的创建合适的索引正确的创建合适的索引。那么许多小伙伴们就想知道为什么呢?其实呢,正确的创建合适的索引是数据库性能优化的基础,大家可能就会说我又不是要当专门管理数据库的人,我要求这么多干嘛?当然,我不能强求什么,但是我对自己的要求就是这样,比较我想在Java开发这条路上越走越远,因为我还是想在将来当上架构师的,毕竟,每个人都要有梦想的,咸鱼总想翻身。

索引到底是什么

索引是关系型数据库为了加速对表中的数据检索的(磁盘存储的)数据结构
数据结构与算法是我们计算机开发人员必须要了解的东西。
(磁盘存储的)数据结构,为什么是磁盘当中的呢,其实不难理解。关系型数据就是存储在磁盘当中的,索引就是存储在磁盘当中的数据结构,比如说一张表有20个字段,我们有三个索引,这三个索引占用的空间。其实也是非常大的,我们不可能把一张表的三个索引结构存在内存中,这是不现实的。既然是存储在磁盘当中的,那么就会有操作系统跟磁盘交互的特性。操作系统跟磁盘交互是非常浪费性能的。
普通的理解就是索引比作一本书籍的目录,这个其实是对加速对表中的数据检索的说明,是索引功能性的一个说明,这个理解当然没有错误,这就是基本的一个理解,如果对它的本质没有了解,我认为这个答案当然是不够完美的。给我一个对应的id,这样一个条件,我可以快速的会给你一个对应的id列值代表的行记录,例如,一张表有若干条数据,多个字段,我拿到其中一条行的id,通过一种数据结构保存一张表的id,通过id,我可以找到对应的id值代表的行记录的磁盘指针,我拿到这个磁盘指针,我可以去找到磁盘指针对应的行记录,并将行记录返回给我们的请求端。这就是索引工作的流程模型。
这关系型数据库中,能作为索引的数据结构的本质,一般分为两种,一种为hash表,一种为树型结构。
hash表,在Java当中,它的一维结构是数组,采用外链法,为什么采用外链法,数组里面的,因为hash表中的哈希函数存在碰撞的情况,比如,如果要在hash表中存入有a的内容,a会通过哈希函数计算出一个hash值,这个hash值如何知道它在数组中的下标呢,就是这个值与数组长度进行相关的计算。hashMap的源码当中是高低16位的异或运算。因为存在碰撞的情况,当不同的对象计算出相同的hash值的时候,就会在数组的某一位置,形成一个链表或者是树的结构,以加速它的查找过程。(JDK1.7以前是数组加链表,JDK1.8+就是数组加链表加红黑树)但是整个hash表的数据的·插入或者说数据的存储以及搜索的过程。是采用的数组下标的一个搜索过程。时间复杂度O(1),O(1)可以看做是查找一个常量的级别。所以说hash表在关系型数据库当中一般称为哈希索引。

哈希索引

如果说我们底层最终采用的索引是以哈希表的形式来存储的话,其实它有几个特点。
哈希的通过一个计算存在一个问题,原值是可以排序的,但是经过计算后,无法进行排序,所以说哈希索引的第一个弊端是哈希索引不支持范围查找,也不支持模糊查找。所以说哈希索引它的优势是等值比对非常高效。
比如通过Navicat,设计一张表的时候,设计一个索引,通过图形化工具操作设计索引的时候是可以看到索引方式有BTREE结构的,其实在索引方式里面点击下拉箭头,可以看到还有hash结构的。所以说hash索引是存在的,只是说我们用到的INNODB引擎不支持用户级别的哈希索引。所以说我们大家对这一块内容,不是很了解,或者说压根没有接触过。

树型索引

树型索引为什么能够作为一个索引的本质呢,它非常简单的容易理解,它是通过递归的二分查找,比如说在一个二叉树的结构,我们要去查找一个数据,首先二叉树的排列一定是有规则的,它的排列规则是左小右大的规则,比根节点还要小的,一定是在它的左子树上面。

二叉查找树

二叉查找树,第一个插入的数据作为根节点,比他小的在左,反之在右,但是,如果,后续插入的值,呈现一种逐渐递增的形式,最终会形成一个线性的链表的一个结构,如果说你在这个线性的链表上面进行查找,这种情况就比较麻烦了,假如说,你要查找的数在这链表的最后,你就必须查找整个链表,这就是二叉查找树的弊端,即二叉查找树在数据组织的阶段有可能会出现一种不规整的情况,而导致形成我们的线性链表的结构,导致我们的查询带来的是更大的消耗。所以说这一种结构虽然从理论上是满足索引的要求,但是它确实有一定的诟病。那么我们可能会想在二叉树的基础上做一定的平衡,不就可以了吗?好,平衡二叉树它就来了。

平衡二叉树

这个二叉树结构的话会相对的平衡,在平衡二叉树当中的任何一个节点,它的子节点的高度差,不允许大于1,比如说,一个节点,它的左边直接连的左子节点,它的高度为1,它的右边没有子节点的,所以说右边的高度为0,1-0的绝对值不能大于1,如果大于1,就违背了二叉树的平衡性。平衡二叉树在数据的插入、修改是有相关的计算和排列的一些方式在里面。可以解决上面的线性的问题,通过旋转。那么平衡二叉树为什么没有被MYSQL这种关系型数据库作为索引底层呢,主要是若你要查询的数据需要经过(子节点数据区与磁盘指针)一层层的比对,层级越多,磁盘的交互次数过多(IO次数过多),这个肯定是不合理的,这是它的第一个毛病;那么第二个毛病是什么呢,一次磁盘的交互(IO操作),只能加载一个节点的信息。
操作系统最基本的工作单位是操作系统页 ,操作系统页 一般的大小是4KB,操作系统与磁盘的交互是通过页大小,来交互的,最小都是4KB,如果我们只是一个很简单的查找一个int类型的数据,可能只花费几十byte,这也就是说,我们做一次磁盘IO操作,花费4KB,会浪费很多的空间,所以说,平衡二叉树与磁盘的操作,体现了
第二个弊端,就是IO的饱和度,也叫IO的效率,实际上就是IO的利用率不高
。现在有这么多的弊端,平衡二叉树在磁盘级的操作是不行了,那么,我们就会针对问题,找出解决办法,那么在关系型数据库当中,我们比较喜欢的多路平衡查找树(B-Tree)它就来了。

多路平衡查找树(B-Tree)

这种结构是关系型数据库索引的首选,或者很多的数据库底层索引是基于B-Tree进行加强(MYSQL做的B-plus),变种,改造(Oracle的B*)。说一个二三树,很容易理解,就是一个节点它的子节点要么是两个,要么是是三个。多路平衡查找树,多路 相较的就是二叉树,路,我们可以理解为一个节点的子节点,比二多可以说是多路,而且它是完全平衡的, 这个意味着这一棵树型结构的所有的叶子节点全部在一个水平线上。
好像忘记了说树里面的构造了,就是,可以分为关键字,数据区,和子节点引用。一个关键字代表的是数据库中的表的一行记录。
在MYSQL当中一个节点,或者说一个磁盘块就是一个数据库页,16KB,那么为什么是16kb呢?那是因为操作系统跟磁盘还有一个原则,就是空间局部性原理,空间局部性原理是操作系统读取磁盘里面的文件,比如说a.txt,那么,当我开始读文件信息的头部信息的时候,操作系统就会认为我马上要其余的信息,它就会进行预加载的一个操作,也就是预读,这个就是空间局部性原理,操作系统与磁盘的交互,虽然是以操作系统页为单位的,但是它一次交互,并非只交互4KB,它有可能交互16KB,有可能交互64KB,因为它有预读的空间局部原理要遵循。为什么一定是16KB呢,因为MYSQL数据库层面强制要求基于MYSQL发出来的操作系统层面的一个磁盘请求以16KB为大小来进行数据的一个加载,也就是说一次加载一个数据库页(在这里指的可以是一个子节点),16KB,如果关键字是int类型,一个int类型是4byte,一个数据区4byte,再加上子节点引用,比如说8byte,16KB从理论上讲能存几个关键字呢,能存1000个,这里能代表什么呢,就代表,我们能存1000条行数据的id记录,那么这个节点的最近的子节点,可以保存多少条数据呢,1000*1000,也就是100w,那么这是第二层,第三层呢,1000的立方,第四层,1000的四次方…
那么这样IO的次数已经降低的了,这样的结构,我们普通的数据库,三四层就足够存储了。
一次加载1000条,到内存里面,在内存里面比对,肯定比在磁盘里面比对更加迅速。这样IO的执行效率就提高了
这就是为什么,关系型数据结构把B树结构作为宠儿,因为它大大的规避了磁盘存储的索引结构。
好了,本次就暂时说到这吧,b+树,下次有想法了,再说吧。
最后,一个小彩蛋,BTree的模拟网站

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值