文章内容整顿自【博学谷狂野架构师】

索引(index)是帮忙MySQL高效获取数据数据结构(有序)。在数据之外,数据库系统还保护着满足 特定查找算法的数据结构,这些数据结构以某种形式援用(指向)数据, 这样就能够在这些数据结构 上实现高级查找算法,这种数据结构就是索引。


优缺点:

长处:

  • 进步数据检索效率,升高数据库的IO老本
  • 通过索引列对数据进行排序,升高数据排序的老本,升高CPU的耗费

毛病:

  • 索引列也是要占用空间的
  • 索引大大提高了查问效率,但升高了更新的速度,比方 INSERT、UPDATE、DELETE

索引构造

索引构造形容
B+Tree最常见的索引类型,大部分引擎都反对B+树索引
Hash底层数据结构是用哈希表实现,只有准确匹配索引列的查问才无效,不反对范畴查问
R-Tree(空间索引)空间索引是 MyISAM 引擎的一个非凡索引类型,次要用于天文空间数据类型,通常应用较少
Full-Text(全文索引)是一种通过建设倒排索引,疾速匹配文档的形式,相似于 Lucene, Solr, ES
  • 上述是MySQL中所反对的所有的索引构造,接下来,咱们再来看看不同的存储引擎对于索引构造的反对 状况。
索引InnoDBMyISAMMemory
B+Tree索引反对反对反对
Hash索引不反对不反对反对
R-Tree索引不反对反对不反对
Full-text5.6版本之后反对反对不反对
留神: 咱们平时所说的索引,如果没有特地指明,都是指B+树结构组织的索引。

二叉树

如果说MySQL的索引构造采纳二叉树的数据结构,比拟现实的构造如下:

如果主键是程序插入的,则会造成一个单向链表,构造如下:

所以,如果抉择二叉树作为索引构造,会存在以下毛病:

  • 程序插入时,会造成一个链表,查问性能大大降低。
  • 大数据量状况下,层级较深,检索速度慢。

此时大家可能会想到,咱们能够抉择红黑树,红黑树是一颗自均衡二叉树,那这样即便是程序插入数据,最终造成的数据结构也是一颗均衡的二叉树,构造如下:

然而,即使如此,因为红黑树也是一颗二叉树,所以也会存在一个毛病:

  • 大数据量状况下,层级较深,检索速度慢。

所以,在MySQL的索引构造中,并没有抉择二叉树或者红黑树,而抉择的是B+Tree,那么什么是B+Tree呢?在详解B+Tree之前,先来介绍一个B-Tree。

B-Tree

B-Tree,B树是一种多路衡查找树,绝对于二叉树,B树每个节点能够有多个分支,即多叉。以一颗最大度数(max-degree)为5(5阶)的b-tree为例,那这个B树每个节点最多存储4个key,5个指针:

树的度数指的是一个节点的子节点个数。

咱们能够通过一个数据结构可视化的网站来简略演示一下。B-Tree Visualization (usfca.edu)(opens new window)

插入一组数据: 100 65 169 368 900 556 780 35 215 1200 234 888 158 90 1000 88 120 268 250 。而后察看一些数据插入过程中,节点的变动状况。

特点:

  • 5阶的B树,每一个节点最多存储4个key,对应5个指针。
  • 一旦节点存储的key数量达到5,就会裂变,两头元素向上决裂。
  • B树中,非叶子节点和叶子节点都会存放数据

B+Tree

B+Tree是B-Tree的变种,咱们以一颗最大度数(max-degree)为4(4阶)的b+tree为例,来看一下其构造示意图:


咱们能够看到,两局部:

  • 绿色框框起来的局部,是索引局部,仅仅起到索引数据的作用,不存储数据。
  • 红色框框起来的局部,是数据存储局部,在其叶子节点中要存储具体的数据。

咱们能够通过一个数据结构可视化的网站来简略演示一下。B+ Tree Visualization (usfca.edu)(opens new window)


插入一组数据: 100 65 169 368 900 556 780 35 215 1200 234 888 158 90 1000 88 120 268 250 。而后察看一些数据插入过程中,节点的变动状况。

最终咱们看到,B+Tree 与 B-Tree相比,次要有以下三点区别:

  • 所有的数据都会呈现在叶子节点
  • 叶子节点造成一个单向链表
  • 非叶子节点仅仅起到索引数据作用具体的数据都是在叶子节点寄存的。

上述咱们所看到的构造是规范的B+Tree的数据结构,接下来,咱们再来看看MySQL中优化之后的B+Tree。

MySQL索引数据结构对经典的B+Tree进行了优化。在原B+Tree的根底上,减少一个指向相邻叶子节点的链表指针,就造成了带有程序指针的B+Tree,进步区间拜访的性能,利于排序。

Hash

MySQL中除了反对B+Tree索引,还反对一种索引类型---Hash索引。

  1. 构造

哈希索引就是采纳肯定的hash算法,将键值换算成新的hash值,映射到对应的槽位上,而后存储在hash表中。

如果两个(或多个)键值,映射到一个雷同的槽位上,他们就产生了hash抵触(也称为hash碰撞),能够通过链表来解决。

  1. 特点
  • Hash索引只能用于对等比拟(=,in),不反对范畴查问(between,>,< ,...)
  • 无奈利用索引实现排序操作
  • 查问效率高,通常(不存在hash抵触的状况)只须要一次检索就能够了,效率通常要高于B+tree索引
  1. 存储引擎反对

在MySQL中,反对hash索引的是Memory存储引擎。 而InnoDB中具备自适应hash性能,hash索引是 InnoDB存储引擎依据B+Tree索引在指定条件下主动构建的。

思考题: 为什么InnoDB存储引擎抉择应用B+tree索引构造?

  1. 绝对于二叉树,层级更少,搜寻效率高;
  2. 对于B-tree,无论是叶子节点还是非叶子节点,都会保留数据,这样导致一页中存储的键值缩小指针跟着缩小,要同样保留大量数据只能减少树的高度,导致性能升高
  3. 绝对Hash索引,B+tree反对范畴匹配及排序操作;

索引的分类

在MySQL数据库,将索引的具体类型次要分为以下几类:主键索引、惟一索引、惯例索引、全文索引。

分类含意特点关键字
主键索引针对于表中主键创立的索引默认主动创立,只能有一个PRIMARY
惟一索引防止同一个表中某数据列中的值反复能够有多个UNIQUE
惯例索引疾速定位特定数据能够有多个
全文索引全文索引查找的是文本中的关键词,而不是比拟索引中的值能够有多个FULLTEXT

在 InnoDB 存储引擎中,依据索引的存储模式,又能够分为以下两种:

分类含意特点
汇集索引(Clustered Index)将数据存储与索引放一块,索引构造的叶子节点保留了行数据必须有,而且只有一个
二级索引(Secondary Index)将数据与索引离开存储,索引构造的叶子节点关联的是对应的主键能够存在多个

汇集索引选取规定:

  • 如果存在主键,主键索引就是汇集索引
  • 如果不存在主键,将应用第一个惟一(UNIQUE)索引作为汇集索引。
  • 如果表没有主键,或没有适合的惟一索引,则InnoDB会主动生成一个rowid作为暗藏的汇集索 引。

汇集索引和二级索引的具体构造如下:

演示图:

  • 汇集索引的叶子节点下挂的是这一行的数据 。
  • 二级索引的叶子节点下挂的是该字段值对应的主键值。

接下来,咱们来剖析一下,当咱们执行如下的SQL语句时,具体的查找过程是什么样子的。

具体过程如下:

  1. 因为是依据name字段进行查问,所以先依据name='Arm'到name字段的二级索引中进行匹配查 找。然而在二级索引中只能查找到 Arm 对应的主键值 10。
  2. 因为查问返回的数据是*,所以此时,还须要依据主键值10,到汇集索引中查找10对应的记录,最 终找到10对应的行row。
  3. 最终拿到这一行的数据,间接返回即可。

回表查问: 这种先到二级索引中查找数据,找到主键值,而后再到汇集索引中依据主键值,获取 数据的形式,就称之为回表查问。

思考题:

  • 以下两条SQL语句,那个执行效率高? 为什么?

    A. select * from user where id = 10 ;

    B. select * from user where name = 'Arm' ;

    备注: id为主键,name字段创立的有索引;

解答:

  • A 语句的执行性能要高于B 语句。
  • 因为A语句间接走汇集索引,间接返回数据。 而B语句须要先查问name字段的二级索引,而后再查问汇集索引,也就是须要进行回表查问。

思考题:

  • InnoDB主键索引的B+tree高度为多高呢?

答:假如一行数据大小为1k,一页中能够存储16行这样的数据。InnoDB 的指针占用6个字节的空间,主键假如为bigint,占用字节数为8. 可得公式:n * 8 + (n + 1) * 6 = 16 * 1024,其中 8 示意 bigint 占用的字节数,n 示意以后节点存储的key的数量,(n + 1) 示意指针数量(比key多一个)。算出n约为1170。

如果树的高度为2,那么他能存储的数据量大略为:1171 * 16 = 18736; 如果树的高度为3,那么他能存储的数据量大略为:1171 * 1171 * 16 = 21939856

另外,如果有成千上万的数据,那么就要思考分表,波及运维篇常识

如果本文对您有帮忙,欢送关注点赞`,您的反对是我保持创作的能源。

转载请注明出处!