索引(下)
覆盖索引
通过联合索引将所有字段囊括,查询时就不需要进行回表操作,称为覆盖索引。
最左前缀原则
字段满足联合索引最左N个字段,就可以利用索引进行查询。
一般来说当存在索引(a,b)后,不需要再单独为a建立索引。但需要查询条件只有b的语句无法使用(a,b)这个联合索引,所以说要同时维护(a,b)和(b)这两个索引。考虑空间问题,建议a是较大的字段。
MySQL 8.0.19:
一个主键以及一个联合索引(name,age)。
当以name进行查询时:
当以age进行查询时:
Extra=using where;using index,Type=index貌似使用上了,使用了name_age索引。这是个问题。
索引下推
MySQL5.6以前,当索引无法覆盖全部条件字段,仅会将索引第一个字段满足条件的记录取出回表查询。
MySQL5.6以后,会同时先判断索引其他字段的满足条件再取出回表查询。
using where 进行了回表,将数据传给server层,server层在临时内存中进行判断。
using index condition 表示可以进行索引下推。
问题
CREATE TABLE `geek` (
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
`c` int(11) NOT NULL,
`d` int(11) NOT NULL,
PRIMARY KEY (`a`,`b`),
KEY `c` (`c`),
KEY `ca` (`c`,`a`),
KEY `cb` (`c`,`b`)
) ENGINE=InnoDB;
既然主键包含了 a、b 这两个字段,那意味着单独在字段 c 上创建一个索引,就已经包含了三个字段了呀,为什么要创建“ca”“cb”这两个索引?
同事告诉他,是因为他们的业务里面有这样的两种语句:
select * from geek where c=N order by a limit 1;
select * from geek where c=N order by b limit 1;
为了这两个查询模式,这两个索引是否都是必须的?为什么呢?
首先因为联合主键a&b的原因,数据以先a再b排序。
在sql语句 select * from geek where c = N order by a limit 1; c索引和ca索引没有区别,因为a默认都会进行排序。
在sql语句 select * from geek order by c 中则是先o再a,c索引和ca索引也没有区别。
而由于默认以先a再b排序,所以cb有必要保留。