最近在学习MySQL,在网上看到一篇博客:mysql 联合索引 复合索引(abc)如何索引命中规则实测

但是博客中的一个点引起了我的注意:

索引都用上的情况下复合索引顺序 复合索引(a,b,c)_索引都用上的情况下复合索引顺序


嗯哼?明明对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;

然后随便插入了一些数据。

开测!

索引都用上的情况下复合索引顺序 复合索引(a,b,c)_联合索引_02


可以看到确实是用到了索引。但是小伙伴发出了质疑,你看Extra里面有个“Using where”,这是不是说明回表查询了?

这个“Using where”看起来的确可疑,但是都索引覆盖了,不至于去回表吧?

然后我把大于号改成等于号,结果如下:就没有了“Using where”

索引都用上的情况下复合索引顺序 复合索引(a,b,c)_innodb_03

那就查一下同时出现“Using where”和“Using index”的含义吧。
果然,6年前就有人提过这个问题:Whats the difference between “Using index” and “Using where; Using index” in the EXPLAIN

文章里面解释到,同时出现了“Using where;Using index”,也是走了索引,只不过对索引的键进行了范围判断而已。

接下来,从联合索引的B+树的角度来看,联合索引的最左列到底能不能做范围查找的索引?

索引都用上的情况下复合索引顺序 复合索引(a,b,c)_mysql_04


联合索引的B+,只不过是有多个键值顺序排列而已。

最后,记录一下不同查询索引,的explain 的extra项:

为d列建立普通索引,e列无索引。

  1. 无索引
  2. 索引都用上的情况下复合索引顺序 复合索引(a,b,c)_innodb_05

  3. 有索引,且查询结果覆盖索引
  4. 索引都用上的情况下复合索引顺序 复合索引(a,b,c)_索引都用上的情况下复合索引顺序_06

  5. 有索引,且查询结果是主键(也属于覆盖索引)
  6. 索引都用上的情况下复合索引顺序 复合索引(a,b,c)_innodb_07

  7. 有索引,但查询的列不被索引覆盖,需要回表
  8. 索引都用上的情况下复合索引顺序 复合索引(a,b,c)_联合索引_08