有mysql联合索引(A,B,C),那么AC查询会⽤到索引吗?
提到联合索引的使⽤规则,⼀般我们都会想到左匹配原则,为什么是左不是右呢?这是因为即使是联合索引在innodb底层也是使⽤b+树来存放的,各个节点排序的规则就是按照联合索引中多个字段从左往右依次排序的,所以查询的时候需要左匹配才能保证b+树中的数据是有序的,才能查询;如果单独查询最右侧字段,那么其在b+索引树⾥⾯是完全⽆序的,⾃然也就⽆法查询。
那么有这样⼀个问题,架设联合索引idx_a_b_c(a, b, c),其中针对a和c两个字段进⾏查询是否能够使⽤索引呢?⼤家可以先暂停,⾃⼰思考⼀下~
相信⼤家经过思考已经有了⾃⼰的答案,那么我们⼀起去探索求证⼀下吧。
我这⾥使⽤的mysql版本为5.7.25
⾸先,我们创建⼀张表:将字段a,b,c设置为联合索引。
create table `my_index_test` (
`id` int(11) unsigned not null auto_increment comment '主键id',
`column_a` int(11) unsigned not null default 0 comment '字段a',mysql 要钱吗
`column_b` int(11) unsigned not null default 0 comment '字段b',
`column_c` int(11) unsigned not null default 0 comment '字段c',
`column_d` int(11) unsigned not null default 0 comment '字段d',
primary key (`id`),
key `idx_a_b_c` (`column_a`, `column_b`, `column_c`)
) ENGINE=InnoDB comment="联合索引测试";
我们再插⼊⼀些测试数据
DELIMITER //
CREATE PROCEDURE batch_insert()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i <= 10000 DO
INSERT INTO my_index_test(column_a,column_b,column_c,column_d) VALUES(i,i,i,i);
SET i=i+1;
END WHILE;
END;
//
call batch_insert();
接下来我们分析⼀下查询语句:
1. ⾸先我们来看常规的a,b,c查询:
可以发现正常使⽤到了联合索引,在我们的意料之中
2. 我们再来看⼀下b,c查询:
这⾥⼤家要注意了,可能些同学看到explain语句分析的结果中key为idx_a_b_c就认为这条查询语句使⽤到了索引,觉得效率很⾼,更重要的b,c查询不符合左匹配的原则,为什么还会⽤到索引呢?这⾥稍微解释⼀下type字段,在这个例⼦中我们看到type为index,它的意思是对索引进⾏全表扫描,在上⾯的例⼦中就是对idx_a_b_c索引进⾏全扫描,索引中的数据量是等于全表数据量的,换句话说type为index是另⼀种形式的全表扫描。
有同学可能会问那么innodb为什么会这么⼲呢?稍微在扩展⼀下:
这是因为我们select的字段"column_a"是存在于索引上,不需要回表再去查的。所以innodb引擎判断直接在idx_a_b_c上进⾏全扫描即可完成任务,并且⽐在聚簇索引上进⾏全表扫描会更加节省内存,更
加快速。如果我把语句改为“select column_d from my_index_test where column_b=3 and column_c = 1”,注意“column_d”字段不在任何索引上。
可以发现这次已经是type=all全表扫描了。有上述疑惑的同学们这下应该理解了吧~
好了我们⾔归正传,来验证下最初的问题a,c会使⽤到索引吗?
可以看到a,c查询也是会⽤到idx_a_b_c索引的。
如何理解这个结果呢?开篇我们已经说过了联合索引在innodb底层的存储和排序⽅式:数据⾸先在a字段的维度进⾏排序,然后在b字段维度排序,最后是c字段,从左向右依次类推,最终存放在b+树⾥。如果搜索条件是a,c的话,虽然c在结果区间是⽆序的(中间有⼀层b),但是单单是⽤a字段就可以把结果区间圈定在⼀个很⼩的范围内,肯定是⽐全表扫描需要遍历的字段要少对吧。
⾄于为什么⽹上去查资料很多都是a,c不⽀持的回答,想必是早期的innodb版本没有把优化做到这⼀步,还有待看源码确认,但是相信像能够阅读到这的优秀同学如果看到innodb居然不⽀持a,c使⽤联合索引,也会想着亲⾃去优化innodb的吧~
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论