mysql索引

索引介绍

索引是一种特殊的数据结构,其主要目的就是为了加快数据的查询速度。
mysql索引基于表的指定字段,按照某种数据结构进行排序,并将数据集存储于实际的文件中。
mysql索引中也记录了索引字段和表真实记录之间的映射关系,当我们基于索引查询到数据时,再基于该映射关系,据可以快速定位到真实记录行所在的位置,并实现快速的读取。

为什么基于索引的查询要比普通查询快?

由于索引时按照特定数据结构进行组织的(如B+树、Hash),因此在查询数据的时候,可以在低于O(N)(全部扫描)的方式,查询到目标数据,所以其查询速度就非常快。
基于索引的查询速度比较快的最本质原因就是,减少了本次查询的IO次数,从而加快了索引。

举个例子,假设一张mysql表有1000页,我们查询的数据恰巧在第1000页的最后。看看两种查询的效果。

  • 全表扫描:一页一页的顺序遍历,最后在第1000页的最后一行找到我们想要的数据,最后计算查询总共进行了1000次IO
  • 基于索引的查询: 假设索引结构是一个B+树结构,且层高为3层,那么查询时,首先基于索引进行检索,进行3次IO即可获取目标数据所在的页,然后对该数据页进行加载读取,得到我们需要的数据,最终计算查询总共进行了4次IO

对比两种查询方式,可以发现在数据量大的情况下,索引查询性能远远优于全表扫描。

索引的优缺点
  • 优势:在查询数据时,基于索引进行查询速度很快
  • 弊端:mysql索引是真实存在的文件,因此会占用一定的存储空间;在更新表数据的时候,需要同步更新索引树,这会带来额外的开销

索引分类

在mysql中,可以按照不同方式,对索引进行分类。
按照索引数据结构可以将索引分为:B+树索引、Hash索引。
按照索引中存储的数据,可以将索引分为聚簇索引、辅助索引。
按照索引的字段,可以将索引分为单列索引、联合索引。
按照索引的字段性质,将以将索引分为主键索引、唯一索引、普通索引

按照数据结构区分索引

mysql中最常见的索引就是B+树索引(又称为B树索引)、Hash索引。

B+树索引又叫B树索引,是因为在mysql中,如果索引类型是B+树,显示的结构是:Index_type: BTREE.

其中mysql的Innodb和Mylsam存储引擎支持B树索引,memory存储引擎支持Hash索引。

B+树索引

对指定列中的数据,按照B+树数据结构进行构建,非叶节点用于存储索引信息,叶子节点用于存储真实数据,并且是有序的,这里存储对应的字段数据以及指向真实页的索引。

不仅如此,B+树的叶子节点还会通过双向链表进行连接,以便于进行范围查询。

这里存在一个问题:
索引为什么采取B+树,而不是B-树?
B+ 树非叶节点用于存储索引信息,叶子节点用于存储真实数据。
B-树是所有节点均用于存储真实数据,相比于真实数据,索引数据的size是比较小的,这意味着,B+树的非叶节点可以存储更多的数据,因此可以指向更多的叶子节点。
因此在相同树高下,B+树可以存储的信息要远远大于B树,这就意味着对相同数据量而言,构建B-树需要更多的层高,那么在极端情况下,查询的数据在叶子节点上,则需要更多的IO,效率太低。
另外B+树的数据均存储在叶子节点上,且有序,用链表将叶子节点连接起来,比较适用于范围查询,而B-树则不行。

Hash索引

所谓Hash索引,就是对指定列的数据,按照Hash表数据结果方式进行构建。基于字段值做hash,散列至hash表的某个位置上,Hash表中存储真实的数据。

按照索引中的数据区分索引

按照此类方式来区分索引,mysql中有两类索引:聚簇索引和辅助索引。

聚簇索引

以B+树数据结构的索引为例,叶子节点上如果存储的是对应表上的真实记录的话,那么就称该索引为聚簇索引。

对于mysql的Innodb表而言,如果表中存在主键,那么就会基于主键建立一个聚簇索引,如果没有指定主键的话,那么mysql会自动创建一个隐藏的自增字段,并基于该自增字段来建立聚簇索引。

辅助索引

仍以B树数据结构的索引为例,如果叶子存储的不是对应表中的真实记录,而是存储的是指定字段值与对应表真实记录的映射关系,则称该索引为辅助索引。

通常情况下,我们对表建立的二级索引,称之为辅助索引。

按照索引的字段区分索引

索引可以针对mysql表中的其中一列,也可以针对mysql表中的多列。根据这个特点,可以将索引分为单列索引、联合索引。

单列索引

针对表中的其中一列所建立的索引称之为单列索引。

联合索引

针对表中的多列所建立的索引称之为联合索引。

  • 最左匹配
    针对联合索引的查询,有一个特点,就是遵循最左匹配原则。
    联合索引是基于多个字段构建的,在构建时,这些字段是有序的。
    在针对联合索引的查询,必须要匹配上索引字段的最左字段,否则,联合索引不生效。

举个例子:联合索引是基于A、B、C字段建立,这三个字段按照ABC排列,在查询的时候,查询条件只有匹配到最左侧的A字段时,联合索引才生效。

  • 联合索引为什么要遵循最左匹配原则?
    这是由联合索引的结构所决定的。
    联合索引构建时,会首先以多个字段的最左侧字段进行排序,当有多行数据最左侧字段值相同时,此时联合索引才会再根据索引字段列中的下一个字段进行排序,以此类推。
    因此对于联合索引而言,它是针对最左字段整体有序的,针对其他索引字段是局部有序的。

因此在查询的时候,我们必须要满足最左匹配原则,否则无法确定目标数据在索引中的位置。