【MySQL】最左前缀匹配原则

avatar
作者
猴君
阅读量:0

 

目录

准备库表

结果集在索引列中的查询

1. explain select a,b,c from t where a=1;

2. explain select a,b,c from t where a=1 AND b=2;

3. explain select a,b,c from t where a=1 order by b;

4. explain select a,b,c from t where a=1 order by d;

5. explain select a,b,c from t where b=1;

结果集不在索引列中的查询

1. explain select a,b,c,d from t where a=1;

2. explain select a,b,c,d from t where a=1 AND b=2;

3. explain select a,b,c,d from t where a=1 order by b; 

4. explain select a,b,c,d from t where a=1 order by d;

5. explain select a,b,c,d from t where b=1;

总结


MySQL 版本:8.0.32

通过实战的方式加深对最左前缀匹配原则的理解

准备库表

CREATE TABLE `t` (   `id` int unsigned NOT NULL AUTO_INCREMENT,   `a` int NOT NULL DEFAULT '0',   `b` int NOT NULL DEFAULT '0',   `c` int NOT NULL DEFAULT '0',   `d` int DEFAULT NULL,   PRIMARY KEY (`id`),   KEY `key_a_b_c` (`a`,`b`,`c`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

建立联合索引(a,b,c)

结果集在索引列中的查询

1. explain select a,b,c from t where a=1;

type: ref 表示走普通索引,结果可能有多行

key_len: 4 表示只用到联合索引(a,b,c)的最左前缀 a

Extra: Using index 表示走覆盖索引,不用回表

2. explain select a,b,c from t where a=1 AND b=2;

和 1 差不多,只不过 key_len 是 8,表示用到联合索引(a,b,c)的两个最左前缀 a,b

3. explain select a,b,c from t where a=1 order by b;

和 1 完全相同,因为建立联合索引(a,b,c)后,找到 a 对应的索引列,那么 b 本身就是有序的

4. explain select a,b,c from t where a=1 order by d;

因为使用了索引列之外的列进行排序,所以走了 Using filesort 外部排序

order by 的排序原理是 MySQL 会给每个线程分配一块内存用于排序,称为 sort_buffer,这里会按照 a 索引列匹配,因为 d 在主键索引中,所以回表查出整行,存入 sort_buffer 中,最后对 sort_buffer 中的数据按照字段 d 做快速排序,而排序这个动作可能在内存中完成,也可能需要使用外部排序,因此可能会有性能问题

5. explain select a,b,c from t where b=1;

type: index,因为最左前缀匹配原则,没有命中索引,但因为查询的列都在联合索引列中,走了索引扫描

Extra: Using where; Using index 表示条件过滤,且走了覆盖索引

结果集不在索引列中的查询

1. explain select a,b,c,d from t where a=1;

和只查 a,b,c 唯一的区别是 Extra 列为空,因为查 d 需要回表

2. explain select a,b,c,d from t where a=1 AND b=2;

和只查 a,b,c 唯一的区别是 Extra 列为空,因为查 d 需要回表

3. explain select a,b,c,d from t where a=1 order by b; 

和只查 a,b,c 唯一的区别是 Extra 列为空,因为查 d 需要回表

4. explain select a,b,c,d from t where a=1 order by d;

和只查 a,b,c 完全相同,因为排序字段也会放在 sort_buffer 中

5. explain select a,b,c,d from t where b=1;

type:ALL,因为 d 不在索引列中,索引失效,直接走了全表扫描

Extra:Using Where,按条件过滤

总结

对于结果集在和不在索引列的两种情况,虽然都不符合最左前缀原则,执行计划还是有很大区别的

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!