是什么?
MySQL可以使用多个字段同时建立一个索引,叫做联合索引。
联合索引在B+树中存储的是 联合索引的字段 + 对应主键字段。
MySQL使用索引时需要索引有序,假设现在建立了 “a” 为主键,“b,c,d” 的联合索引。
索引的排序为: 从左往右依次递增,先按照 b 排序,如果 b 有排序结果了,就按它的顺序排列,如果 b 相同,则按照 c 排序,如果 c 的值也相等,则按照 d 进行排序。然后根据查找到的主键回表查找相应的数据。
查找:根据上述找到对应的联合索引后,根据主键索引进行回表查找。
示例
explain select * from t where b = 1 and c = 1 and d =1; --走索引
explain select * from t where c = 1 and d = 1 and d =1; --走索引
explain select * from t where c = 1 and d =1; --不走索引
当进行查询时,此时索引仅仅按照name严格有序,因此必须首先使用name字段进行等值查询,锁定在一定的范围内,之后对于匹配到的列而言,其按照age字段严格有序,此时可以使用age字段用做索引查找,依次类推。
当跳过第一个字段时,除非是第一个字段都是相同的(第一个字段相同会按照第二个字段排序),否则第二个字段都是无序的,就无法进行检索。
explain select * from t where b = 1; --走索引
explain select * from t where b > 1; --不走索引
explain select b from t where b > 1; --走索引
explain select b,c,d,a from t where b > 1; --走索引
explain select b,c,d,a,e from t where b > 1; --走索引
b > 1
确实是可以缩小范围,但是我们要select *
查询所有字段,那么只能根据联合索引查找到的主键索引进行回表查询,数据一多,回表次数就多,性能降低。如果直接通过全表扫描,主键索引去查询, 速度会快的多,所以不走索引。
select b
和select b,c,d,a
查询的字段,刚好在联合索引查询中有,那就直接走索引。
select b,c,d,a,e
中的 e 字段在联合索引查询中没有,需要根据超找到的主键回表查询,那么就不走索引。
explain select b,c,d,a from t; --走联合索引
select b,c,d,a
查找可以走主键索引和联合索引,但在主键索引的B+树中,存储的是完整的字段,而在联合索引中,只存储联合索引的字段和主键索引的字段,同样是16kb的页存储,那么联合索引会存储更多,页数也就会小于走主键索引查询出来的页数,所以走联合索引查询。
explain select * from t order by b asc,c asc ,d asc; --走主键索引
虽然b asc,c asc ,d asc
符合联合索引的排序,但是select *
要查询所有字段,如果根据联合索引找到主键之后,还要去回表查询所有字段,那就比直接走主键索引要慢得多。
mysql会计算成本选择合适的方式的