MySQL 索引

本文粗略说以下 MySQL 中常见的索引分类。

物理存储角度

  • 聚簇索引
  • 非聚簇索引

聚簇索引将数据存储与索引放到了一起,找到索引也就找到了数据。非聚簇索引将数据存储与索引分开,索引结构的叶子结点指向了数据对应的行。

InnoDB 中,在聚簇索引之上创建的索引,称之为辅助索引,辅助索引叶子结点存储的不是行的物理位置,而是主键值,因此辅助索引访问数据总是需要二次查找的。

一图顶千言,如下图所示:

由于聚簇索引是将数据跟索引结构放在一起的,因此一个表仅有一个聚簇索引。

聚簇索引默认是主键,如果表中没有定义主键,InnoDB 会选择一个唯一非空索引,如果没有这样的索引,InnoDB 会隐式定义一个主键来作为聚簇索引。

数据结构角度

  • B-Tree 索引(技术上来说是 B+树)
  • hash 索引
  • FULLTEXT 索引(全文索引)
  • R-Tree 索引

这里着重说以下 B-Tree 索引,B-Tree 索引之所以能加快访问数据的速度,是因为存储引擎不在需要进行全表扫描来获取数据,而是从索引的跟结点开始进行搜索,根节点的槽中存放了指向子节点的指针,存储引擎根据这些指针向下层查找,通过比较节点页的值和要查找的值找到合适的指针进入下层子节点,这些指针定义了子节点页中值的上限和下限。最终存储引擎要么找到对应的值,要么对应的记录不存在。

叶子结点比较特别,它们的指针指向的是被索引的数据,而不是其他的结点页。同时所有的叶子结点到根节点的距离相同,所以 B-Tree 的查询效率非常的稳定。

相较于二叉查找树,B-Tree 在比较次数上并不占优,但是把磁盘里数据加载到内存的时候,是以为单位来加载的,节点与节点之间的数据是不连续的,所以不同的节点,有可能分布在不同的磁盘页中。B-Tree 的每一个节点可以存放多个元素,所以磁盘寻址加载次数会比较少。所以总体来说 B-Tree 还是比二叉查找树快。

B-Tree 适用于全键值、键值范围或建前缀查找(只适用于最左前缀查找)。

逻辑角度

  • 主键索引
  • 普通索引(单列索引)
  • 复合索引(多列索引)
  • 唯一索引