MySQL主键索引(聚簇索引)与非主键索引(二级索引)

一、什么是最左前缀原则

注意:本文基于MySQL的InnoDB引擎说明。

对于该表,如果按照 name 字段来建立索引的话,采用B+树的结构,大概的索引结构如下:

如果要进行模糊查找,查找name 以“张"开头的所有人的ID,即 sql 语句为:

select ID from table where name like '张%'

由于在B+树结构的索引中,索引项是按照索引定义里面出现的字段顺序排序的,索引在查找的时候,可以快速定位到 ID 为 100的张一,然后直接向右遍历所有张开头的人,直到条件不满足为止。也就是说,当找到第一个满足条件的人之后,直接向右遍历就可以了,由于索引是有序的,所有满足条件的人都会聚集在一起。而这种定位到最左边,然后向右遍历寻找的方式,就是我们所说的最左前缀原则

示例:一个(a,b,c)的组合索引。

  1. 通过a,c条件查询能不能使用或命中这个索引?-----能
  2. 通过b,c条件查询能不能使用或命中这个索引?-----不能
  3. 原因:索引文件具有B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。

二、为什么用 B+ 树做索引而不用哈希表做索引

  1. 哈希表是把索引字段映射成对应的哈希码然后再存放在对应的位置,这样的话,如果我们要进行模糊查找的话,显然哈希表这种结构是不支持的,只能遍历这个表。而B+树则可以通过最左前缀原则快速找到对应的数据。
  2. 如果我们要进行范围查找,例如查找ID为100 ~ 400的人,哈希表同样不支持,只能遍历全表。
  3. 索引字段通过哈希映射成哈希码,如果很多字段都刚好映射到相同值的哈希码的话,那么形成的索引结构将会是一条很长的链表,这样的话,查找的时间就会大大增加。

三、主键索引和非主键索引有什么区别

例如下表(其实就是上面的表中增加了一个k字段),且ID是主键。

k

主键索引和非主键索引的示意图如下:

结构对比

其中R代表一整行的值。

由图看出,主键索引和非主键索引的区别是:非主键索引的叶子节点存放的是主键的值,而主键索引的叶子节点存放的是整行数据。非主键索引也被称为二级索引,而主键索引也被称为聚簇索引

1️⃣根据这两种结构进行查询,看看区别:

  1. 如果查询语句是 select * from table where ID = 100,即主键查询的方式,则只需要搜索 ID 这棵 B+树。
  2. 如果查询语句是 select * from table where k = 1,即非主键的查询方式,则先搜索k索引树,得到ID=100,再到ID索引树搜索一次,这个过程也被称为回表。

2️⃣聚集索引和非聚集索引的区别:

  1. 聚集索引表示表中存储的数据按照索引的顺序存储,检索效率比非聚集索引高,但对数据更新影响较大。(比如主键索引)
  2. 非聚集索引表示数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置。非聚集索引检索效率比聚集索引低,但对数据更新影响较小。

四、为什么建议使用主键自增的索引?

对于这棵主键索引的树:

主键索引

如果插入 ID = 650 的一行数据,那么直接在最右边插入就可以了

但是如果插入的是 ID = 350 的一行数据,由于 B+ 树是有序的,那么需要将下面的叶子节点进行移动,腾出位置来插入 ID = 350 的数据,这样就会比较消耗时间。如果刚好 R4 所在的数据页已经满了,需要进行页分裂操作,这样会更加糟糕。

但是,如果主键是自增的,每次插入的 ID 都会比前面的大,那么每次只需要在后面插入就行, 不需要移动位置、分裂等操作,这样可以提高性能。也就是为什么建议使用主键自增的索引。

推荐阅读更多精彩内容