最近在学习MySQL,在网上看到一篇博客:mysql 联合索引 复合索引(abc)如何索引命中规则实测
但是博客中的一个点引起了我的注意:
嗯哼?明明对a,b,c三列做了联合索引,在对a进行范围查找的时候肯定会使用索引啊。
根据最左匹配原则,对a查询肯定会用到a的索引;B+树的叶子节点是双向指针链接起来的,范围查找很适合啊!为啥不用索引?
我迷惑了,既然人家实战了,咱也来实际测试一下。
建表与索引语句如下:
CREATE TABLE `test_copy1` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`a` int(255) NULL DEFAULT NULL,
`b` int(255) NULL DEFAULT NULL,
`c` int(255) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `abc`(`a`, `b`, `c`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
然后随便插入了一些数据。
开测!
可以看到确实是用到了索引。但是小伙伴发出了质疑,你看Extra里面有个“Using where”,这是不是说明回表查询了?
这个“Using where”看起来的确可疑,但是都索引覆盖了,不至于去回表吧?
然后我把大于号改成等于号,结果如下:就没有了“Using where”
那就查一下同时出现“Using where”和“Using index”的含义吧。
果然,6年前就有人提过这个问题:Whats the difference between “Using index” and “Using where; Using index” in the EXPLAIN
文章里面解释到,同时出现了“Using where;Using index”,也是走了索引,只不过对索引的键进行了范围判断而已。
接下来,从联合索引的B+树的角度来看,联合索引的最左列到底能不能做范围查找的索引?
联合索引的B+,只不过是有多个键值顺序排列而已。
最后,记录一下不同查询索引,的explain 的extra项:
为d列建立普通索引,e列无索引。
- 无索引
- 有索引,且查询结果覆盖索引
- 有索引,且查询结果是主键(也属于覆盖索引)
- 有索引,但查询的列不被索引覆盖,需要回表