关于Mysql索引你必定要知道的(上)

关于Mysql索引你必定要知道的

导图

索引模型

Hash

简介

Hash索引是MEMORY引擎默认使用的索引结构,也只有MEMORY引擎能够显式使用Hash索引,实际上就是HashTable,key-value结构。同时也是用拉链法解决hash冲突,这里不展开讨论。html

结构

iShot2021-07-04 11.58.14.png

这里须要注意的是HashTable的Value里面并非直接存储的单行数据而是存的是指针。mysql

特色

  1. 在哈希索引中没有存索引字段的信息,因此并不能经过索引值来减小读取行数
  2. 哈希索引不是有序的,因此并不能作排序
  3. 哈希因此不支持索引匹配查找,好比说b+树索引可以使用最左匹配原则去使用联合索引,而哈希索引不能。也就是说在数据列(A,B)上创建哈希索引,若是查询只有数据列A,则没法使用该索引。
  4. 哈希索引进行检索效率很是高,基本上一次检索就能够找到数据,从检索次数上来讲比B+树索引要少得多
  5. 只支持等值查询,范围查询不支持
  6. 当哈希碰撞过多的时候,索引的维护代价很高

B树

简介

若是咱们要了解B+树,就必定要先了解B树,B树是为磁盘等直接存储的辅助存储设备而设计的一种平衡搜索树,它的节点能够存储多个关键字,而且它是一个多叉树,一个B树知足如下条件:算法

先解释几个词:sql

  • 关键字:每一个节点存储的数据
  • x:每一个节点存储关键字的数量
  • m:树的高度

定义:数据库

  1. 是一颗有根树
  2. 每一个节点包含x+1个指向孩子节点的指针
  3. 每一个节点的所存储的关键字以非降序排列,每一个数据的左子树中的全部数据都小于它,而右子树中的全部数据都大于它。
  4. 每一个叶节点都有相同的深度,即树的高度,也能够说成叶结点都位于同一层
  5. 每一个节点至多有m-1个数据
  6. 根节点最少能够只有1个数据

数据结构

如图这是一个3阶B树 iShot2021-07-04 11.59.08.pngmarkdown

插入删除

B树的插入主要涉及三个步骤,查询、插入、分裂。数据结构

  • 查询:这里指的是找到插入位置,这里的查找和二叉搜索树的查找相似
  • 插入:关键字插入过程
  • 分裂:为了保持B树的结构,当节点关键字数量达到阈值,就会产生分裂动做,中间关键字提高到父节点,其余节点生成两棵新子树

B树的删除其实和插入很是类似,只是更加复杂一点,由于删除能够从任意节点删除,而并不是只能从叶子节点删除。因此就涉及到删除后保持结构定义的过程。这里就再也不赘述删除具体的流程,比较复杂。建议你们去看一下《算法导论》286页,有详细的描述。oop

动画

这里能够看到 Max. Degree = 3 表示是一个三阶B树,因此他的关键字最多只能有三个。性能

  1. 当咱们插入1,树是空的,因此直接插入。
  2. 插入3,因为3大于1,而且当前节点关键字小于3,因此放在同一个节点1后面的位置.
  3. 插入5,5大于3因此在3后面,当前节点的关键字=3,触发分裂,中间关键字3向上升入根节点,1,5生成两个新子树
  4. 插入4,4大于根节点3,因此往右边查找,小于5,而且节点关键字数小于3
  5. 删除1,找到1的位置,删除,发现左子树为空了,不知足定义,004关键字上升成为根结点,003,005分别为左右节点。

这时候若是咱们再插入1,就会发现,结构并不会恢复成以前的样子。 动画

查询

其实从刚刚的插入删除的演示中就已经能够看出查询的过程,搜索一颗B树和搜索一颗二叉搜索树相似,不一样的就在于每一个节点的分支选择是多叉的,而不必定是二叉。

为何B树(N叉)适合作索引

为了探究这个问题咱们首先应该了解几个知识

  • 索引的存储

索引就是一种数据结构,须要存储,而且索引也不仅仅在内存中,须要存储到磁盘中。

  • 影响数据库查询速度的因素

在我以前的博文中提到过,实际上数据库查询数据是先查主存,若是不存在,才去磁盘中查询,而后带到主存里来。这里在磁盘查询的过程当中会涉及到磁盘的io,实际上若是不考虑从主存中查询,最影响数据库查询速度的就是磁盘IO,所以尽可能减小磁盘IO就能够显著的提高数据的查询速度。

  • 预读机制

传统的磁盘读取依靠的是机械运动,IO的耗时就分为寻道时间、旋转延迟、传输时间三个部分。**SSD则不一样。**为了减小io的消耗,采用来预读的机制。当访问一个地址数据的时候,与其相邻的数据很快也会被访问到。每次磁盘IO读取的数据咱们称之为一页(page)。一页的大小与操做系统有关,通常为4k或者8k。这也就意味着读取一页内数据的时候,实际上发生了一次磁盘IO。

经过上面几点,咱们就能够知道,索引会写盘,查询索引的过程就是查询节点的过程若是不在内存中就会去查找磁盘,产生磁盘IO,那么索引的查询速度大部分就取决于每次查询须要访问的数据页。咱们能够假设一棵 100 万节点的平衡二叉树,树高 20。一次查询可能须要访问 20 个数据块。而若是使用b树的话就取决于咱们N叉树的N的大小。固然,这里B+树也是同理的。

B+树

简介

B+树其实就是B树和顺序索引访问方法演化而来的,在这里就不赘述B树和B+树的区别了,你们只要知道B树的每一个结点都存储了key和data,B+树的data存储在叶子节点上。

结构

B+树其实就是B树的变体,和B树很类似。如图是一个三阶B+树。

插入和删除

从图中咱们能够和清楚的看到,实际上B+树的插入和删除的过程和B树基本一致,惟一区别是,B+树经过一个双向链表把叶子节点连接起来,在维护树的时候一样须要维护这个双向链表,这里也不仔细去说详细的插入删除的算法。详见《Mysql技术内幕 InnoDB存储引擎》 P202

查询

查询过程其实也是接近的,区别只是B+树的节点没有存储data,因此其实是查到链表中。

区别

  1. B+树改进了B树, 让非叶子结点只做索引使用, 去掉了其中指向data record的指针, 使得每一个结点中可以存放更多的key, 所以能有更大的扇出数。
  2. 叶子结点使用链表形式链接。

非叶子节点不存储数据就意味着存放一样多的key, 树的层高能进一步被压缩, 使得检索的时间更短。而且叶子结点是链表形式,能更快的进行顺序遍历。

聚簇索引(clustered index)

也就是主键索引,叶子节点存储的是整行的数据,而且数据也是依据主键索引进行排序,主键索引一张表只能有一个也是由于数据只能按照一个索引进行排序。聚簇索引附带惟一性约束。

非聚簇索引(secondary index)

也叫辅助索引,叶子节点并不存放整行数据,而是存储主键的值。要查找到完整数据须要回表。

惟一索引

用来确保表中没有两个数据行具备彻底相同的键值通常咱们使用它来帮助维护数据完整性。同时须要注意惟一性约束不等于惟一索引。

非惟一索引

普通索引,用来辅助查询,不具有惟一性约束。

页分裂

索引按照顺序递增(不必定要连续,只要是递增就行),索引紧凑;随机插入为了保证索引的顺序行可能会形成索引的数据页分裂。数据页的分裂就产生数据空洞。分裂过程不只影响性能还会影响空间使用率,由于本来一个数据页的数据,分红了两个数据页。 固然有分裂就有合并。当相邻两个页因为删除了数据,利用率很低以后,会将数据页作合并。合并的过程,能够认为是分裂过程的逆过程。

这里引用一张《Mysql 45讲》中的图

回表

非聚簇索引查询到主键,回到聚簇索引搜索的过程,咱们称为回表。

覆盖索引

覆盖索引并非一种索引类型,而是从非聚簇索引中就能够查询到的结果不用,再去回表。这种操做能够的好处是,非聚簇索引只存储索引值,并无整行的数据,故其大小远小于聚簇索引,能够减小大量的io操做,因此咱们常说不要用select *。

联合索引

联合索引是指对表上的多个列进行索引,联合索引也是一棵B+树,不一样的是联合索引的键值数量不是1,而是大于等于2。 这里须要注意的是联合索引的结构 联合索引的全部索引列都出如今索引树上,并依次比较三列的大小进行排序。

做者水平有限,如有错误遗漏,请指出。

参考文章

1.MySQL索引背后的数据结构及算法原理

2.stackoverflow

3.深刻理解数据库索引采用B树和B+树的缘由

4.MySQL实战45讲

5.MySQL技术内幕 InnoDB存储引擎 第2版

相关文章
相关标签/搜索