一、什么是索引?
索引说白了就是数据的目录。
二、索引的分类
四个分类角度
- 数据结构: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前的字段是索引,而后面的字段不是索引,索引会失效