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 时要 遵循索引的顺序,才能发挥索引的最大性能!🚀

相关推荐
好奇的菜鸟3 小时前
如何在IntelliJ IDEA中设置数据库连接全局共享
java·数据库·intellij-idea
tan180°3 小时前
MySQL表的操作(3)
linux·数据库·c++·vscode·后端·mysql
满昕欢喜3 小时前
SQL Server从入门到项目实践(超值版)读书笔记 20
数据库·sql·sqlserver
哲科软件3 小时前
跨平台开发的抉择:Flutter vs 原生安卓(Kotlin)的优劣对比与选型建议
android·flutter·kotlin
DuelCode4 小时前
Windows VMWare Centos Docker部署Springboot 应用实现文件上传返回文件http链接
java·spring boot·mysql·nginx·docker·centos·mybatis
幽络源小助理4 小时前
SpringBoot基于Mysql的商业辅助决策系统设计与实现
java·vue.js·spring boot·后端·mysql·spring
Hello.Reader4 小时前
Redis 延迟排查与优化全攻略
数据库·redis·缓存
简佐义的博客5 小时前
破解非模式物种GO/KEGG注释难题
开发语言·数据库·后端·oracle·golang
爬山算法5 小时前
MySQL(116)如何监控负载均衡状态?
数据库·mysql·负载均衡
老纪的技术唠嗑局8 小时前
OceanBase PoC 经验总结(二)—— AP 业务
数据库