MySQL InnoDB引擎下的索引 | 青训营笔记

66 阅读4分钟

这是我参与「第五届青训营 」笔记创作活动的第6天

前言

扫了眼之前的博客,发现MySQL有些点有点忘了,索性复习一下。

在InnoDB存储引擎中,表都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(index organized table)。
在InnoDB存储引擎表中,每张表都有个主键(Primary Key),如果在创建表时没有显式地定义主键,则InnoDB存储引擎会按如下方式选择或创建主键:

  • 首先判断表中是否有非空的唯一索引(Unique NOT NULL),如果有,则该列即为主键(如果有多个,则选取定义索引顺序的第一个,而不是定义列的顺序)
  • 如果不符合上述条件,InnoDB存储引擎自动创建一个6字节大小的指针

InnoDB索引分类

image.png

一般B+树索引用的比较多。

B+树索引

聚集索引

聚集索引,又叫主键索引,按照每张表的主键构建一颗B+树,一个索引就是一颗B+树,叶子节点(数据页)存放整张表的行记录数据。

特点

  • 聚集索引的存储并不是物理上连续,而是逻辑上连续

    • 页通过双向链表链接,页按照主键的顺序排序
    • 每个页中的记录也是通过双向链表进行维护的
  • 由于实际的数据页只能按照一棵B+树进行排序,因此每张表只能拥有一个聚集索引

  • 在多数情况下,查询优化器倾向于采用聚集索引。因为聚集索引能够在B+树索引的叶子节点上直接找到数据

  • 此外,由于定义了数据的逻辑顺序,聚集索引能够特别快地访问针对范围值的查询和排序

非聚集索引

辅助索引(Secondary Index,也称非聚集索引),叶子节点并不包含行记录的全部数据。叶子节点除了包含键值以外,每个叶子节点中的索引行中还包含了一个书签(bookmark)。该书签用来告诉InnoDB存储引擎哪里可以找到与索引相对应的行数据。由于InnoDB存储引擎表是索引组织表,因此InnoDB存储引擎的辅助索引的书签就是相应行数据的聚集索引键

特点

  • 辅助索引的存在并不影响数据在聚集索引中的组织,因此每张表上可以有多个辅助索引

查找过程

查找一个非聚集索引,InnoDB引擎首先会遍历非聚集索引B+树,通过页级别的 指针找到指向聚集索引的键ID,然后通过这个ID键再去查找聚集索引,得到一个完整的行数据,这个过程叫做回表
例子:

  • 如果语句是 select * from T where ID=500,即主键查询方式,则只需要搜索 ID 这棵 B+ 树;
  • 如果语句是 select * from T where k=5,即普通索引查询方式,则需要先搜索 k 索引树,得到 ID 的值为 500,再到 ID 索引树搜索一次

索引维护

在插入新纪录、删除旧纪录时,B+ 树为了维护索引有序性,会涉及到索引的维护问题。

  • 如果 在上图中插入ID=700的记录,则在R5后面插入一条新记录就行;
  • 如果插入ID=400的记录,则需要移动R4,R5,然后把ID=400插进去;更糟糕的,如果R4所在的页满了,就需要申请新的页,挪动部分数据到新页上面(页分裂

注意:

  • 页分裂会降低空间利用率、性能
  • 主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小

索引应用

最左前缀匹配原则

联合索引中,如果你的 SQL 语句中用到了联合索引中的最左边的索引,那么这条 SQL 语句就可以利用这个联合索引去进行匹配。 这个最左前缀可以是:

  • 联合索引的最左 N 个字段;
  • 也可以是字符串索引的最左 M 个字符

参考&鸣谢