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

相关推荐
2501_916013748 小时前
iOS 推送开发完整指南,APNs 配置、证书申请、远程推送实现与上架调试经验分享
android·ios·小程序·https·uni-app·iphone·webview
李艺为10 小时前
非预置应用使用platform签名并且添加了android.uid.system无法adb安装解决方法
android·adb
李宥小哥12 小时前
C#基础11-常用类
android·java·c#
悟能不能悟12 小时前
redis的红锁
数据库·redis·缓存
贝多芬也爱敲代码14 小时前
如何减小ES和mysql的同步时间差
大数据·mysql·elasticsearch
安当加密14 小时前
MySQL数据库透明加密(TDE)解决方案:基于国密SM4的合规与性能优化实践
数据库·mysql·性能优化
007php00715 小时前
某大厂跳动面试:计算机网络相关问题解析与总结
java·开发语言·学习·计算机网络·mysql·面试·职场和发展
JH307315 小时前
第七篇:Buffer Pool 与 InnoDB 其他组件的协作
java·数据库·mysql·oracle
板凳坐着晒太阳15 小时前
ClickHouse 配置优化与问题解决
数据库·clickhouse