如何实现MySQL的索引

 更新时间:2022年01月26日 17:42:04   作者: LiveEveryDay   
这篇文章主要介绍了如何实现MySQL的索引,MySQL中索引分三类,有B+树索引、Hash索引和全文索引,下面我们一起来看看MySQL索引的具体实现,需要的小伙伴可以参考一下

MySQL中索引分三类:B+树索引、Hash索引、全文索引。InnoDB存储引擎中用的是B+树索引。要介绍B+树索引,不得不提二叉查找树、平衡二叉树和B树这三种数据结构。B+树是从它们三个演化来的。

二叉查找树:

图中为user表建立了一个二叉查找树的索引。节点中存储了键(key)和数据(data)。数据对应user表中的行数据。

如果查找id=12的用户信息,流程如下:
1)将根节点作为当前节点,12大于10,将10的右子节点(13节点)作为当前节点。
2)12与13比较,将13的左子节点(12节点)作为当前节点。
3)12与12比较,满足条件,从当前节点去除data,即id=12,name=xm。
利用二叉查找树,3次可找到匹配数据。如果在表中一条一条查找,需要6次。

平衡二叉树:

如果上面的二叉树这样构造:

变成了一个链表,查询id=17的用户信息,需要查7次,相当于全表扫描。导致这个现象是因为二叉查找树不平衡了。为了解决这个问题,需要用平衡二叉树。
平衡二叉树又称 AVL 树,在满足二叉查找树特性的基础上,要求每个节点的左右子树的高度差不能超过 1。

B树:
因为内存的易失性,一般会将数据和索引存储到磁盘中。和内存比,从磁盘读数据会慢很多,所以应当减少读取次数。此外,从磁盘读数据按照磁盘块来读取,而非一条一条的读。
如果我们能把尽可能多的数据放进磁盘块中,那一次磁盘读取操作就会读取更多数据,那我们查找数据的时间也会大幅度降低。如果我们用树这种数据结构作为索引的数据结构,那我们每查找一次数据就需要从磁盘中读取一个节点,也就是我们说的一个磁盘块。我们都知道平衡二叉树可是每个节点只存储一个键值和数据的。那说明什么?说明每个磁盘块仅仅存储一个键值和数据!那如果我们要存储海量的数据呢?
可以想象到二叉树的节点将会非常多,高度也会极其高,我们查找数据时也会进行很多次磁盘 IO,我们查找数据的效率将会极低!
为了解决平衡二叉树的这个弊端,我们应该寻找一种单个节点可以存储多个键值和数据的平衡树。也就是我们接下来要说的 B 树。

图中的每个节点称为页(就是磁盘块),在MySQL中数据读取的基本单位都是页。每个节点存储了更多的键值和数据。子节点的个数一般称为阶,上述图中B树为3阶B树。
查找id=28的用户信息,

流程如下:

  • 1)先找到根节点也就是页 1,判断 28 在键值 17 和 35 之间,那么我们根据页 1 中的指针 p2 找到页 3。
  • 2)将 28 和页 3 中的键值相比较,28 在 26 和 30 之间,我们根据页 3 中的指针 p2 找到页 8。
  • 3)将 28 和页 8 中的键值相比较,发现有匹配的键值 28,键值 28 对应的用户信息为(28,bv)。

B+树:

B+树是对B树的进化,其不同:

  • 1)B+树非叶子节点不存储数据,仅存储键值,B树则存储键值和数据(为什么这么做?数据库中页的大小是固定的,InnoDB中默认是16KB,如果不存数据,就可以存更多的键值,树的阶数会更大,树就会更矮胖,查找数据进行磁盘IO的次数就会减少,查询效率快)。一般根节点是常驻内存的。
  • 2)B+树索引的所有数据存储在叶子节点,而且数据是按照顺序排列的(使得范围查找、排序查找、分组查找及去重查找很简单,而B树因为数据分散在各个节点,实现这一点很不容易),B+树的叶子节点中的数据通过单向链表连接,各个页之间通过双向链表连接。

过上图可以看到,在 InnoDB 中,我们通过数据页之间通过双向链表连接以及叶子节点中数据之间通过单向链表连接的方式可以找到表中所有的数据。

在 MySQL 中,B+ 树索引按照存储方式的不同分为聚集索引和非聚集索引。

利用聚集索引查找数据:

现在假设我们要查找 id>=18 并且 id<40 的用户数据。

对应的 sql 语句为:

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

其中id为主键,具体的查找过程如下:

  • 1)一般根节点常驻内存的,页1已经在内存中了,不用读磁盘,直接内存读取。
  • 在内存中页1查找id>=18 and id<40或者范围值,先找到id=18的键值。从页1找到指针p2,定位到页3。
  • 2)从磁盘中读取页3,然后将页3放入内存中,然后进行查找,可以找到键值18,然后拿到页3中的指针p1,定位到页8。
  • 3)将页8读取到内存中,根据二分查找法定位到键值18, 因为是范围查找,而且此时所有的数据又都存在叶子节点,并且是有序排列的,那么我们就可以对页 8 中的键值依次进行遍历查找并匹配满足条件的数据。
  • 我们可以一直找到键值为 22 的数据,然后页 8 中就没有数据了,此时我们需要拿着页 8 中的 p 指针去读取页 9 中的数据。
  • 4)因为页 9 不在内存中,就又会加载页 9 到内存中,并通过和页 8 中一样的方式进行数据的查找,直到将页 12 加载到内存中,发现 41 大于 40,此时不满足条件。那么查找到此终止。

具体流程图:

利用非聚集索引查找数据:

查找幸运数字为33的用户信息,需要回表。

到此这篇关于如何实现MySQL的索引的文章就介绍到这了,更多相关实现MySQL的索引内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL主备操作以及原理详解

    MySQL主备操作以及原理详解

    本文主要介绍了MySQL主备操作以及原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • 解决mysql不是内部或外部命令的问题

    解决mysql不是内部或外部命令的问题

    这篇文章主要介绍了解决mysql不是内部或外部命令的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • deepin20.1系统安装MySQL8.0.23(超详细的MySQL8安装教程)

    deepin20.1系统安装MySQL8.0.23(超详细的MySQL8安装教程)

    这篇文章主要介绍了deepin20.1系统安装MySQL8.0.23(最美国产Liunx系统,最详细的MySQL8安装教程),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • mysql 截取指定的两个字符串之间的内容

    mysql 截取指定的两个字符串之间的内容

    今天我同事在用mysql的时候,需要对一个字符串中的指定内容进行截取
    2009-07-07
  • Linux系统下修改mysql字符集为UTF8步骤

    Linux系统下修改mysql字符集为UTF8步骤

    大家好,本篇文章主要分享的是Linux系统下修改mysql字符集为UTF8步骤,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下吧,方便下次浏览
    2021-12-12
  • MySQL主从同步原理及应用

    MySQL主从同步原理及应用

    日常工作中,MySQL数据库是必不可少的存储,其中读写分离基本是标配,而这背后需要MySQL开启主从同步,形成一主一从、或一主多从的架构。本篇文章我们就来解绍MySQL主从同步原理及应用,需要的朋友可以参考一下
    2021-10-10
  • mysql错误处理之ERROR 1665 (HY000)

    mysql错误处理之ERROR 1665 (HY000)

    最近一直在mysql的各个版本直接徘徊,这中间遇到了各种各样的错误,将已经处理完毕的几个错误整理了一下,分享给大家,这次我们来看看错误提示 ERROR 1665 (HY000)
    2014-07-07
  • SQL实现时间序列错位还原案列

    SQL实现时间序列错位还原案列

    这篇文章小编主要向大家介绍的是时间序列错位还原之SQL实现案例详解的相关资料,需要的小伙伴可以参考下面文章的具体内容
    2021-09-09
  • Mysql使用kill命令解决死锁问题

    Mysql使用kill命令解决死锁问题

    这篇文章主要介绍了Mysql使用kill命令解决死锁问题的相关资料,需要的朋友可以参考下
    2017-06-06
  • MySQL初学者可以告别分组聚合查询的困扰了

    MySQL初学者可以告别分组聚合查询的困扰了

    这篇文章主要为大家介绍了MySQL分组聚合查询的难点讲解,帮助MySQL初学着告别分组聚合查询的困扰,有需要的朋友可以借鉴参考下,希望能够有所进步
    2021-10-10

最新评论