图解MySQL索引(上)—MySQL有中“8种”索引?

关于MySQL索引相关的内容,一直是一个让人头疼的问题,尤为是对于初学者来讲。笔者曾在很长一段时间内深陷其中,没法分清“覆盖索引,辅助索引,惟一索引,Hash索引,B-Tree索引……”究竟是些什么东西,致使在面试过程当中进入比较尴尬的局面。html

不少人可能会抱怨”面试造火箭,工做拧螺丝,不少知识都是为了面试学的,工做中根本用不到!“。庆幸的是,MySQL中索引不只是面试必考知识,仍是工做中用到最为频繁的必备技能,在笔者看来,索引是MySQL中性价比最高的一部份内容面试

因为MySQL中支持多种存储引擎,在不一样的存储引擎中实现略微有所差距,索引下文中若是没有特殊声明,默认指的都是InnoDB存储引擎,下文中索引基于这张user表来进行演示。数据库

id name age
001 Lily 18
002 Tom 20
003 Jack 19
004 John 28
005 Alice 24
006 Lucy 21
007 Rose 18
008 Steven 16

1、索引的底层数据结构

首先,索引是高效获取数据的数据结构。就像书中的目录同样,咱们能够经过它快速定位到数据所在的位置,从而提升数据查询的效率。编程

在MySQL中有许多关于索引的名词和概念,对于初学者来讲很容易被迷惑。为了方便理解,我创建了一张表,从具体的案例中尝试说清楚这些概念究竟是什么。数据结构

Hash索引app

正如上文中说到,索引是提升查询效率的数据结构,而可以提升查询效率的数据结构有不少,如二叉搜索树,红黑树,跳表,哈希表(散列表)等,而MySQL中用到了B+Tree和散列表(Hash表)做为索引的底层数据结构。编程语言

须要注意的是,MySQL并无显式支持Hash索引,而是做为内部的一种优化,对于热点的数据会自动生成Hash索引,也叫自适应Hash索引性能

Hash索引在等值查询中,能够O(1)时间复杂度定位到数据,效率很是高,可是不支持范围查询。在许多编程语言以及数据库中都会用到这个数据结构,如Redis支持的Hash数据结构。具体结构以下:优化

B+Tree索引spa

提到B+Tree首先不的不提B-Tree,B-Tree(多路搜索树,并非二叉的)是一种常见的数据结构。使用B-tree结构能够显著减小定位记录时所经历的中间过程,从而加快存取速度。

B+ 树是基于B-Tree升级后的一种树数据结构,一般用于数据库和操做系统的文件系统中。B+ 树的特色是可以保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。B+ 树元素自底向上插入,这与二叉树刚好相反。

MySQL索引的实现也是基于这种高效的数据结构。具体数据结构以下:

笔者首先要声明一下,不要将B树,B-Tree以及B+Tree弄混淆。首先,B-Tree就是B树,中间的“-”是一个中划线,而不是减号,并不存在"B减树"这种数据结构。其次,就是B+Tree和B-Tree实现索引时有两个区别,具体可见下图

①B+Tree只在叶子节点存储数据,而B-Tree的数据存储在各个节点中

②B+Tree的叶子节点间经过指针连接,能够经过遍历叶子节点便可获取全部数据。

B+Tree是一种神奇的数据结构,若是用语言来说可能会优势费劲,感兴趣的同窗能够点击这里进行数据结构可视化,操做一番后想必会有所收获,下图是笔者演示B+Tree的数据插入方式(自下而上)。

二,数据组织方式

根据数据的组织方式,能够分为聚簇索引和非聚簇索引(也叫汇集索引和非汇集索引)。若是是索引组织数据,就称之为聚簇索引,不然称之为非聚簇索引,简单来讲索引和数据是否存储在一块儿

须要注意的是,这种索引划分方式一般用来体现不一样存储引擎的组织数据方式的差别(一般指的是InnoDB和MyISAM存储引擎)。而InnoDB中的辅助索引并不能称之为非聚簇索引,关于辅助索引的内容,下文会进行详细介绍。InnoDB中是经过索引来组织数据,为聚簇索引。

而MyISAM中索引和数据文件分开存储,为非聚簇索引。B+Tree的叶子节点存储的是数据存放的地址,而不是具体的数据 。

三,索引字段个数

为了能应对不一样的数据检索需求,索引便可以仅包含一个字段,也能够同时包含多个字段。单个字段组成的索引能够称为单值索引,不然称之为复合索引(或者称为组合索引或多值索引)。上文中演示的都是单值索引,因此接下来展现一下复合索引做为对比。

复合索引的索引的数据顺序跟字段的顺序相关,包含多个值的索引中,若是当前面字段的值重复时,将会按照其后面的值进行排序。

四, 是否存储完整数据行

MySQL中是根据主键来组织数据,因此每张表都必须有主键索引,主键索引只能有一个,不能为null同时必须保证惟一性。建表时若是没有指定主键索引,则会自动生成一个隐藏的字段做为主键索引。

若是不是主键索引,则就能够称之为非主键索引,又能够称之为辅助索引,二级索引。主键索引的叶子节点存储了完整的数据行,而非主键索引的叶子节点存储的则是主键索引值,经过非主键索引查询数据时,会先查找到主键索引,而后再到主键索引上去查找对应的数据,这个过程叫作回表(下文中会再次提到)。

五,其余分类

惟一索引

惟一索引,不容许具备索引值相同的行,从而禁止重复的索引或键值。系统在建立该索引时检查是否有重复的键值,并在每次使用 INSERT 或 UPDATE 语句添加数据时进行检查, 若是有重复的值,则会操做失败,抛出异常。

须要注意的时,主键索引必定时惟一索引,而惟一索引不必定时主键索引。惟一索引能够理解为仅仅是将索引设置一个惟一性的属性

覆盖索引

上文提到了一个回表的概念,既若是经过非主键索引查询数据时,会先查询到主键索引的值,而后再去主键索引中查询具体的数据,整个查询流程须要扫描两次索引,显然回表是一个耗时的操做。

为了减小回表次数,再设计索引时咱们能够让索引中包含要查询的结果,在辅助索引中检索到数据后直接返回,而不须要进行回表操做。

可是须要注意的是,使用覆盖索引的前提是字段长度比较短,对于值长度较长的字段则不适合使用覆盖索引,缘由有不少,好比索引通常存储在内存中,若是占用空间较大,则可能会从磁盘中加载,影响性能。固然还有其余缘由,具体状况将会在下一篇文章中介绍。

六,总结

本文从不一样维度介绍了MySQL中的索引,索引从不一样维度划分能够有不少种名称,可是须要明确一个问题就是,索引的本质是一种数据结构,其余索引的划分则是针对实际应用而言。具体分类以下图所示:

目的是让你们对于索引有个初步且清晰的认识,解决What的问题。后续将会针对Why以及How,进行深刻探讨,固然,首先应当能区分本章文章中讲述的概念性问题。

7、Q&A

1. 为何MySQL索引使用B+Tree实现,而不是搜索二叉树,红黑树或者跳表?

这是一个综合性问题,远不止看起来那么简单,小伙伴们能够把答案写在留言区咱们一块儿探讨,一样笔者将会在下一篇文章中重点介绍为何,以及如何正确使用索引。

相关文章
相关标签/搜索