【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索引时有感而发,进行分享记录,感谢阅读支持(●'◡'●)

相关推荐
ZWZhangYu2 小时前
LangChain 构建向量数据库和检索器
数据库·langchain·easyui
feifeigo1233 小时前
升级到MySQL 8.4,MySQL启动报错:io_setup() failed with EAGAIN
数据库·mysql·adb
火龙谷4 小时前
【nosql】有哪些非关系型数据库?
数据库·nosql
焱焱枫5 小时前
Oracle获取执行计划之10046 技术详解
数据库·oracle
qq_392397127 小时前
Redis常用操作
数据库·redis·wpf
一只fish8 小时前
MySQL 8.0 OCP 1Z0-908 题目解析(17)
数据库·mysql
花好月圆春祺夏安9 小时前
基于odoo17的设计模式详解---装饰模式
数据库·python·设计模式
A__tao9 小时前
SQL 转 Java 实体类工具
java·数据库·sql
m0_653031369 小时前
腾讯云认证考试报名 - TDSQL数据库交付运维专家(TCCE PostgreSQL版)
运维·数据库·腾讯云
小马哥编程10 小时前
【iSAQB软件架构】架构决策记录-ADR
数据库·架构·系统架构·设计规范