索引与MySQL

103 阅读3分钟

一、什么是索引?

索引说白了就是数据的目录。

二、索引的分类

四个分类角度

  • 数据结构:B+tree索引、Hash索引(InnoDB不支持)、Full-text索引
  • 物理存储:聚簇索引(主键索引)、(非聚簇索引)二级索引
  • 字段特性:主键索引、唯一索引、普通索引、前缀索引
  • 字段个数:单列索引、联合索引

不同的存储引擎对索引的支持也不相同,由于MySQL5.5之后默认存储引擎为InnoDB,而InnoDB使用最多的是B+Tree索引,所以本文着重介绍InnoDB中的B+Tree索引,当然InnoDB也支持Full-text索引。

在创建表时,选取索引的规则如下

  • 如果有主键,默认主键作为聚簇索引的索引键
  • 如果没有主键,就选择第一个不包含NULL值的唯一列作为聚簇索引的索引键
  • 上面两个都不满足的情况下,InnoDB将自动生成一个隐式自增id作为聚簇索引的索引键

主键索引与二级索引

主键索引:B+Tree的叶子节点存放的是完整的数据记录,一条记录的所有信息都包含在其中

二级索引:B+Tree的叶子节点存放的主键

因为B+Tree叶子节点存放数据的区别,也就引发了回表查询

回表查询就是通过二级索引查询到主键之后,还需要通过主键索引再进行查询,所以回表查询也是造成查询效率低的一种情况,可以通过覆盖索引进行优化,也就是要查询的内容,可以在二级索引的B+Tree中查询到。

三、最左匹配原则

当使用联合索引的时候,B+Tree中的节点,存有多个字段进行排序,而这些字段的排序就是联合索引建立时字段的顺序。以下索引,会先按照name进行排序,当name相同时,则按照age进行排序。

CREATE INDEX index_name_age ON user(name, age);

联合索引的最左匹配原则在遇到某些情况的时候会失效:

  • 在遇到范围匹配的时候,如>、<,后面的字段不会用到联合索引
  • 遇到like模糊匹配时,如"%he"

tips:

1.between ... and ...不会失效

2.like "he%"不会失效

四、索引选择性

索引选择性 = distinct(column)/count(*)

如下查询,sex性别作为索引,则其区分度就比较低,而学号则每个学生都不一样,可以唯一区分一个学生,在建立索引的时候应该尽量让索性选择性低。

select * from student where id_no = 1 and sex = 1

联合索引进行排序:有时候sql中涉及到排序,我们可以利用索引的有序性,避免文件排序。

select * from order where status = 1 order by create_time asc

五、索引的建立

基于最左匹配原则和索引选择性的考量,通常可以通过如下几个方面对索引进行优化:

  • 通过覆盖索引,避免回表查询
  • 减少索引字段的大小,如通过前缀索引,比较选择性(身份证倒序建立)
  • 经常更新的字段不要建立索引,因为索引的有序性,索引字段更新后,会进行动态维护
  • 索引字段最好设置为Not NUll

六、索引失效

实际生产中,并不是建立了索引就万事大吉了,在使用中,也会出现索引失效,常见的索引失效场景如下

  • 对索引使用左模糊匹配,eg: like "%he"
  • 对索引使用函数
  • 对索引使用表达式计算
  • 对索引进行了隐式类型转换
  • 联合索引非最左匹配
  • where子句中出现了or,如果在or前的字段是索引,而后面的字段不是索引,索引会失效