【MySQL】联合索引和覆盖索引(索引失效的误区讲解+案例分析)

(前置知识:最好知道联合索引覆盖索引是啥,不知道的话文章里也有简要定义可供参考学习 文章前半部分没什么代码和图片请见谅,最后会有一个清晰的综合案例验证,有基础的朋友可以直接跳转到最后的案例( ̄▽ ̄))

索引失效 和 不满足最左前缀匹配原则 的误区

我们在学习联合索引的时候知道,要使联合索引生效,必须满足"最左前缀匹配原则",即针对(a,b,c)的联合索引,符合条件的字段只能是a ab abc这三种最左前缀

案例1:查询条件是b=1 AND c=1; bc不属于以上三种,就不满足"最左前缀匹配原则" 案例2:查询条件是a=1 AND c=1;这里的查询字段是ac,只满足最左前缀a,所以这个查询条件的a是走联合索引的,而c不走联合索引,仅作为过滤条件

以上的案例相信足够使你了解"最左前缀匹配原则"了,笔者当时学习的时候也是通过这两个案例了解的,但是也就是这里让笔者产生了一个很久之后才发现的误区: 在案例1中,不满足最左前缀匹配原则的查询,是否意味着在本次查询的时候是索引失效的?

先讲结论:不满足最左前缀匹配原则≠索引失效

当时笔者认为不满足"最左前缀匹配原则",不走索引,可不就是索引失效吗?其实不然,这里就要引出覆盖索引的概念了。

覆盖索引

覆盖索引并非是一种独立的索引类型,而是一种基于 联合索引 的 查询优化策略 (初学者谨记该定义) 覆盖索引要求我们查询的字段包含在联合索引中 ,比如联合索引是(a,b,c),而我们SELECT的字段只有b,c,这时候我们查询索引便可以直接获得数据,不用进行回表(不明白回表操作的可以先了解聚簇/非聚簇索引,明白了索引和数据存储的具体关系再来看)

为什么说"不满足最左前缀匹配原则≠索引失效"呢?原因就在覆盖索引,如果查询语句恰好 不满足最左前缀匹配原则 而 满足覆盖索引 那么即便我们不走联合索引,我们也会进行 全索引扫描 获取目标字段值,相比 全表扫描 更快,此时可认为索引仍然参与加速,不算严格索引失效

结合SQL代码进行案例分析

知道EXPLAIN的用法,知道type的的类型

EXPLAIN:在 SQL 语句前添加 EXPLAIN,可分析查询的执行计划

type(访问类型,性能核心指标):

  • const:通过主键或唯一索引直接定位单行(最优)
  • ref:使用非唯一索引或联合索引前缀匹配(高效)
  • range:索引范围扫描(如 BETWEEN>
  • index:全索引扫描(比全表快,但需优化)
  • ALL:全表扫描(需避免,除非数据量极小)
sql 复制代码
-- 创建数据表
CREATE TABLE student (
    id INT NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    s_name VARCHAR(50) NOT NULL COMMENT '姓名',
    score1 INT COMMENT '分数1',
    score2 INT COMMENT '分数2',
    age INT COMMENT '年龄',
    PRIMARY KEY (id), -- zizen主键
    INDEX idx_name_score (a_name, score1, score2)  -- 联合索引
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO student (s_name, score1, score2, age) VALUES
('张三', 34, 89, 20),
('李四', 72, 15, 19),
('王五', 95, 63, 22),
('赵六', 41, 78, 18),
('陈七', 56, 29, 21),
('刘芳', 88, 50, 20),
('周杰', 12, 94, 19),
('吴磊', 67, 38, 21),
('孙悦', 23, 81, 22),
('黄欣', 45, 72, 18),
('郑浩', 90, 11, 20),
('林静', 19, 85, 19),
('郭强', 83, 44, 21),
('何敏', 27, 66, 18),
('高飞', 50, 97, 22),
('徐丽', 61, 33, 20),
('马涛', 78, 55, 21),
('韩梅', 3, 89, 19),
('曹阳', 94, 22, 18),
('邓超', 38, 73, 22);

EXPLAIN SELECT * FROM student WHERE id=5;                                     -- 执行结果:type:const / key:primary
EXPLAIN SELECT * FROM student WHERE s_name='邓超';                                  -- type:ref / key:idx_name_age
EXPLAIN SELECT * FROM student WHERE id>=5;                                             -- type:range / key:primary
EXPLAIN SELECT score1,score2 FROM student WHERE score1>=60 AND score2>=60;        -- type:index / key:idx_name_age
EXPLAIN SELECT score1,score2,age FROM student WHERE score1>=60 AND score2>=60;            -- type:all / key:(NULL)
EXPLAIN SELECT score1,score2 FROM student WHERE score1>=60 AND score2>=60 and age>=20;    -- type:all / key:(NULL)
EXPLAIN SELECT score1,score2,age FROM student WHERE score1>=60 AND score2>=60 and age>20; -- type:all / key:(NULL)

在以上的代码中我们创建了一张学生表,共5个字段:id,name,score1,score2,age 其中id为自增主键,(name,score1,score2)构成一个联合索引:

  • 其中第四条语句,就是本文前面的不满足最左前缀匹配原则≠索引失效的案例,虽然where条件不符合最左前缀匹配原则,但是走的全索引扫描,不算索引失效
  • 而第五句多查了个age,不在联合索引中,就是既不满足最左前缀匹配原则,又不满足覆盖索引,这种才算索引失效

笔者较菜,第一次写文章,内容不长,复习MySQL索引时有感而发,进行分享记录,感谢阅读支持(●'◡'●)

相关推荐
一码归一码@1 小时前
Mysql进阶之事务原理
数据库·mysql
老邓计算机毕设8 小时前
SSM学生选课系统xvbna(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·学生选课系统·ssm 框架·高校教学管理
枷锁—sha9 小时前
【PortSwigger Academy】SQL 注入绕过登录 (Login Bypass)
数据库·sql·学习·安全·网络安全
逍遥德11 小时前
PostgreSQL 中唯一约束(UNIQUE CONSTRAINT) 和唯一索引(UNIQUE INDEX) 的核心区别
数据库·sql·postgresql·dba
工业甲酰苯胺11 小时前
字符串分割并展开成表格的SQL实现方法
数据库·sql
科技块儿11 小时前
IP定位技术:游戏反外挂体系中的精准识别引擎
数据库·tcp/ip·游戏
衫水11 小时前
[特殊字符] MySQL 常用指令大全
数据库·mysql·oracle
卓怡学长11 小时前
m115乐购游戏商城系统
java·前端·数据库·spring boot·spring·游戏
小句12 小时前
SQL中JOIN语法详解 GROUP BY语法详解
数据库·sql
阿杰 AJie13 小时前
MySQL 里给表添加索引
数据库·mysql