2-002:MySQL 索引的最左前缀匹配原则是什么?

MySQL 索引的最左前缀匹配原则

最左前缀匹配原则(Leftmost Prefix Matching) 是指:

查询使用了复合索引(联合索引) 时,MySQL 会优先匹配索引的 最左列 ,然后逐步向右匹配,直到遇到无法匹配的列,此时索引匹配停止,不会继续使用后续的列索引。


1. 复合索引示例

假设有一个 user 表,创建了如下 复合索引(联合索引):

sql 复制代码
CREATE INDEX idx_user ON user (name, age, city);

索引顺序

  • 第一列:name
  • 第二列:age
  • 第三列:city

此时,该索引可以加速如下查询:

可以使用索引的查询

sql 复制代码
SELECT * FROM user WHERE name = 'Tom';   -- 只用到了第一列 ✅
SELECT * FROM user WHERE name = 'Tom' AND age = 25;  -- 使用了前两列 ✅
SELECT * FROM user WHERE name = 'Tom' AND age = 25 AND city = 'Beijing';  -- 使用了全部索引列 ✅
SELECT * FROM user WHERE name LIKE 'T%';  -- 模糊匹配最左列 ✅
  • 以上 SQL 都符合 最左前缀匹配原则 ,因此 MySQL 会使用索引

不能使用索引的查询

sql 复制代码
SELECT * FROM user WHERE age = 25;  -- 跳过了第一列 ❌
SELECT * FROM user WHERE city = 'Beijing';  -- 跳过了第一、第二列 ❌
SELECT * FROM user WHERE age = 25 AND city = 'Beijing';  -- 跳过了第一列 ❌
SELECT * FROM user WHERE name LIKE '%T';  -- 以 % 开头 ❌

索引失效的情况

  1. 查询条件不包含索引的最左列 (如 age=25)。
  2. 跳过索引列 (如 age=25 AND city='Beijing',因为 name 没有出现,索引无法使用)。
  3. 最左列使用 % 开头的模糊查询 (如 name LIKE '%T',导致索引失效)。
  4. 在索引列上进行计算、函数操作 (如 WHERE LEFT(name, 2) = 'To',因为 LEFT() 破坏了索引匹配)。

2. 最左前缀索引的匹配规则

假设索引是 (A, B, C, D),查询时:

  • 能匹配 A → 可以使用索引
  • 能匹配 A, B → 可以使用索引
  • 能匹配 A, B, C → 可以使用索引
  • 跳过 A,直接匹配 B 或 C → 索引失效
  • 在 A 上使用函数、计算等操作 → 索引失效

3. 最左前缀匹配优化建议

  1. 尽量遵循索引的列顺序,避免跳过列。

  2. 尽量使用 = 或 IN 进行查询,避免索引失效。

  3. 不要对索引列进行计算或函数操作,否则 MySQL 无法利用索引。

  4. 如果范围查询 (>, <) 出现在某列,则索引匹配会终止,即:部分失效。如:

sql 复制代码
SELECT * FROM user WHERE name = 'Tom' AND age > 25 AND city = 'Beijing';

这里索引只能用到 name, age,但 city 不会被索引,因为 age > 25,使得 city失效。

解析:索引匹配顺序

  • name = 'Tom'索引匹配
  • age > 25索引匹配 ✅(但是因为是范围查询,后续索引匹配终止!
  • city = 'Beijing'索引失效 ❌(不会使用索引

🔴 为什么 city 列的索引失效?

  • MySQL 索引是按照 (name, age, city) 的顺序建立的,索引匹配是按顺序进行的
  • 一旦遇到范围查询(>, <, BETWEEN) ,MySQL 不会继续使用索引后面的列
  • age > 25 是一个范围查询,因此 索引匹配到 age 这里就停止了city 不能再用索引。

4. 总结

  • 最左列必须出现在查询条件中,否则索引失效!
  • 范围查询 (>, <, BETWEEN) 之后的索引列不再生效!
  • 索引匹配是按照最左列依次匹配的,中间不能跳过!

📌 牢记 :写 SQL 时要 遵循索引的顺序,才能发挥索引的最大性能!🚀

相关推荐
马克学长1 小时前
SSM面向乡村振兴服务的产教融合服务平台521gh(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·乡村振兴·ssm 框架·服务平台
u***27611 小时前
C#数据库操作系列---SqlSugar完结篇
网络·数据库·c#
Y***K4342 小时前
MySQL网站
数据库·mysql
q***44812 小时前
postgresql链接详解
数据库·postgresql
菜鸟‍2 小时前
【后端学习】MySQL数据库
数据库·后端·学习·mysql
污斑兔2 小时前
腾讯云 CloudBase 数据库 CRUD 完整指南
数据库·云计算·腾讯云
tuokuac3 小时前
批量新增操作为什么要加@Transactional注解
数据库
alexhilton3 小时前
深入理解withContext和launch的真正区别
android·kotlin·android jetpack
q***9945 小时前
Redis的Spring配置
数据库·redis·spring
S***y3965 小时前
MySQL视频
数据库·mysql