【MySQL】最左前缀匹配原则
创始人
2024-11-14 07:39:36

 

目录

准备库表

结果集在索引列中的查询

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,按条件过滤

总结

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

相关内容

热门资讯

裸辞做“一人公司”,我后悔了 去年这个时候,一位以色列程序员正在东南亚旅行。他顺手把一个在脑子里转了很久的想法做成了产品,一个让任...
南京建成国内首个Pre-6G试... 4月21日,2026全球6G技术与产业生态大会在南京开幕。全息互动技术展台前,一名远在北京的工作人员...
超梵求职受邀参加“2025抖音... 超梵求职受邀参加“2025抖音巨量引擎成人教育行业生态大会”,探讨分享优质内容传播,服务万千学员。 ...
摩托罗拉Razr 2026(R... IT之家 4 月 22 日消息,摩托罗拉宣布新一代 Razr 折叠手机将于 4 月 29 日在美国发...
库克卸任,特纳斯领航:苹果新纪... 苹果首席执行官蒂姆·库克将卸任,硬件工程主管约翰·特纳斯将接任,苹果公司今天宣布此事。 库克将在夏季...