有mysql联合索引(A, B, C),那么AC查询会用到索引吗? - Cgj20060102030405 - 博客园

提到联合索引的使用规则,一般我们都会想到左匹配原则,为什么是左不是右呢?这是因为即使是联合索引在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'``,``  ```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查询:

https://img2020.cnblogs.com/blog/2417322/202107/2417322-20210706163628366-125674552.png

可以发现正常使用到了联合索引,在我们的意料之中

  1. 我们再来看一下b,c查询:

https://img2020.cnblogs.com/blog/2417322/202107/2417322-20210706163748376-1603792618.png

这里大家要注意了,可能些同学看到explain语句分析的结果中key为idx_a_b_c就认为这条查询语句使用到了索引,觉得效率很高,更重要的b,c查询不符合左匹配的原则,为什么还会用到索引呢?这里稍微解释一下type字段,在这个例子中我们看到type为index,它的意思是对索引进行全表扫描,在上面的例子中就是对idx_a_b_c索引进行全扫描,索引中的数据量是等于全表数据量的,换句话说type为index是另一种形式的全表扫描。