一、回表
若有student表如下
id(主键) | name | age |
1 | 路飞 | 18 |
2 | 索隆 | 20 |
我们对id建立索引,然后再对name建立索引。那么当我们执行select * from student where name=?时,由于索引底层数据结构的B+Tree,对name列建立的索引叫做二级索引或者副主索引,这个索引的数据存储的是id(或者唯一列、或者是6字节的row id),如下图,那么我们执行完SQL时,会从name的B+Tree中拿到id,再回到id的B+Tree中去搜索所对应的数据,这个过程就叫做回表
二、索引覆盖
还是,假设有两条语句
select * from student where name=?
select id from student where name=?
此时,就不会再去再去id的对应索引的那颗B+Tree上再去搜索一遍了,这就是索引覆盖
三、最左匹配原则
一帮情况下和组合索引一起使用,例如吧name,age共同建立索引(name,age),假设现在有下面四条sql语句
select * from student where name=? and age=?
select * from student where name=?
select * from student where age=?
select * from student where age=? and name=?
现在问题来了,那个会走组合索引(name,age)?
答案是1,2,4,而3会进行全表扫描,看下图
听名知意,就是最左边开始匹配呗,也就是先匹配name,再来age。虽然2只有name,但是也会走索引。
你可能的疑惑就是4为啥会走索引,其实mysql中有个叫做优化器的东西,他会对这个age和name的顺序进行优化。这样就可以走索引了
优化器简单的说一下,有两种:CBO(基于成本的优化),RBO(基于规则的优化)MySQL默认用的是CBO。
四、索引下推
首先:
数据是存储在磁盘的、MySQL有自己的服务,MySQL服务要跟磁盘发生交互。这样能从磁盘拿到数据
没有索引下推时:
存储引擎先从磁盘中筛选出name符合条件的数据,全部取出,MySQL server再根据age条件筛选一次。这样就得到了符合条件的值。
这样会有大量的IO操作,所以浪费时间和资源
有存索引下推时:
存储引擎先从磁盘中直接筛选出name,age同时都符合条件的数据,不需要server再去做任何的数据筛选
索引下推需要在磁盘上进行数据筛选,原来的筛选是在内存中进行,现在放到了磁盘上进行查找数据的环节,但是,虽然这样看起来成本更高了,可别忘了,索引数据是排序的,所有数据是聚集存放的没所以性能并不会有影响,而且还会减少IO次数,反而会提升性能