MySQL最左前缀匹配原则

一、前言

最左前缀匹配原则是MySQL索引核心高频考点,也是实际开发中最容易索引失效、导致SQL慢查询的重灾区。很多开发者只会背概念,却不懂底层原理、适用场景和失效逻辑。

二、前置实战索引结构

sql 复制代码
KEY `idx_targetType_targetId` (`targetType`, `targetId`)

三、最左前缀原则核心概念

1. 官方定义

针对联合索引(复合索引) ,MySQL的索引匹配遵循最左前缀原则:查询条件必须从联合索引的最左侧字段开始匹配,依次向右匹配,不能跳过左侧字段直接使用右侧字段,否则右侧字段索引完全失效

重点:该原则不是MySQL的语法规则,是InnoDB引擎B+树物理存储结构决定的

2. 底层B+树存储原理

InnoDB所有索引底层都是B+树,联合索引的排序规则是分层排序

  1. 优先按照**索引第一个字段(最左)**全局排序、分组;

  2. 在第一个字段值相同的分组内,再按照第二个字段排序;

  3. 后续字段以此类推。

对应本文索引的底层存储结构:

bash 复制代码
[0,100]、[0,101]、[0,102] -- targetType=0 分组,内部targetId有序 
[1,100]、[1,101]、[1,102] -- targetType=1 分组,内部targetId有序

简单理解:左字段是大分类,右字段是大分类下的小排序,必须先确定大分类,才能精准匹配小排序。

四、全场景索引生效/失效

1. 完全生效场景

场景1:匹配最左字段+右侧精准字段

sql 复制代码
SELECT * FROM report WHERE targetType = 0 AND targetId = 100;

执行流程

  1. B+树精准定位 targetType=0 分组;

  2. 组内通过有序的targetId二分查找,精准定位数据;

  3. 仅一次回表查询完整数据,查询效率极高。

场景2:仅匹配最左首个字段

sql 复制代码
SELECT * FROM report WHERE targetType = 0; 

索引完全生效,可快速定位对应分组所有数据。

2. 完全失效场景

场景:跳过最左字段,直接查询右侧字段

sql 复制代码
SELECT * FROM report WHERE targetId = 100;

失效底层原因

联合索引按targetType分组存储,未指定最左字段,MySQL无法确定需要查询哪个分组,只能遍历所有分组数据,触发全表扫描,索引彻底失效

3. 部分生效场景

核心铁律 :联合索引中,左侧字段使用范围查询(>、<、>=、<=、between),当前字段索引生效,右侧所有字段索引全部失效

sql 复制代码
SELECT * FROM report WHERE targetType > 0 AND targetId = 10;

底层执行流程

  1. targetType > 0:走索引,筛选出所有符合条件的分组数据;

  2. 范围查询会跨多个分组,导致筛选后的结果集中,targetId完全无序,无法使用索引;

  3. targetId = 10:无法走索引,只能将索引筛选后的所有数据全部回表,在内存中逐条过滤匹配;

  4. 最终结果:索引部分生效,回表次数大幅增加,查询性能下降。

五、总结

  1. 联合索引字段顺序优先级:精准匹配字段在前,范围查询字段在后;

  2. 禁止跳过最左字段查询,避免全表扫描;

  3. 范围查询后置,防止右侧所有字段索引失效;

  4. 有序字段优先:优先使用雪花ID、自增ID等趋势递增字段作为索引后缀,适配B+树存储特性。

相关推荐
今天AI了吗6 小时前
Python 基础语法(一):常量、变量、输入输出与运算符
开发语言·数据库·人工智能·python·sql·深度学习·机器学习
夜雪一千7 小时前
MySQL 全局锁是什么?原理、风险、备份踩坑完整实战
android·mysql·adb
lilian2337 小时前
Harmony os 技术实战|拼豆制图27:用单字符编码承载 50 张 70×70 图纸
前端·数据库·华为·harmonyos
皮卡丘不断更8 小时前
手机优先的 Personal Ledger:把账目、学习和复盘放到同一个入口
数据库·sqlite·fastapi·开源项目·个人效率
保卫大狮兄9 小时前
设备管理从台账到报废,完整生命周期一次讲清
数据库·设备管理·设备
数据安全技术观察9 小时前
数据动态脱敏:让脱敏策略跟着数据目录走
大数据·网络·数据库
小席是个热心肠10 小时前
Redis的自我学习
数据库·redis·学习
2601_9657984710 小时前
Salient Theme Setup Guide for Fast Creative WordPress Sites
数据库·web3·php·wordpress
@Mike@10 小时前
09-数据库学习笔记(数据库索引与过滤器)
数据库·笔记
程序员夏洛11 小时前
MySQL 中 count(*)、count(1) 和 count(字段名) 有什么区别?
数据库·mysql