理解最左前缀原则:联合索引命中规则全解析(含流程图)

📌 一句话解释:

联合索引只会从最左边的列开始连续匹配,一旦中断,后面的列就不能再用上索引。


🔍 举个例子说明(表结构):

sql 复制代码
CREATE TABLE user (
  id INT,
  name VARCHAR(50),
  age INT,
  city VARCHAR(50),
  PRIMARY KEY (id),
  INDEX idx_name_age_city(name, age, city)  -- 联合索引
);

我们定义了一个三列的联合索引:(name, age, city),这是我们要讨论的主角。


✅ 下面来看几个查询是否能命中索引?

查询语句 能否用上索引 原因说明
SELECT * FROM user WHERE name = '张三' ✅ 命中 name 最左前缀第1列,完美命中
SELECT * FROM user WHERE name = '张三' AND age = 20 ✅ 命中 name+age 最左前缀连续两列命中
SELECT * FROM user WHERE name = '张三' AND city = '深圳' ✅ 只命中 name 跳过 age,中断了前缀,city 无法用
SELECT * FROM user WHERE age = 20 ❌ 无法命中 缺失 name,最左前缀不满足
SELECT * FROM user WHERE city = '深圳' ❌ 无法命中 不是从最左的 name 开始
SELECT * FROM user WHERE name LIKE '张%' ✅ 命中 name 前缀匹配生效
SELECT * FROM user WHERE name LIKE '%张' ❌ 索引失效 前缀模糊,索引失效(LIKE %开头)

🧠 如何理解"中断了最左前缀"?

比如你有索引 (a, b, c),那么:

  • 你只能匹配:
    • a
    • a, b
    • a, b, c
  • 如果你跳过了 a 或 b ,比如只用了 cb, c,就相当于中间断了,索引就白建了。

📌 补充知识:最左前缀不仅适用于 WHERE,也适用于:

  • GROUP BY
  • ORDER BY
  • DISTINCT
  • ON(JOIN 的连接条件)

例如:

sql 复制代码
SELECT * FROM user ORDER BY name, age;  -- 命中索引
SELECT * FROM user ORDER BY age;        -- ❌ 无法用索引排序

为什么不从最左开始查,就无法匹配呢?

比如有一个 user 表,我们给 name 和 age 建立了一个联合索引 (name, age)

MySQL 复制代码
ALTER TABLE user add INDEX comidx_name_phone (name,age);

联合索引在 B+ 树中是复合的数据结构,按照从左到右的顺序依次建立搜索树 (name 在左边,age 在右边)。

注意,name 是有序的,age 是无序的。当 name 相等的时候,age 才有序。

当我们使用 where name= '张三' and age = '20' 去查询的时候, B+ 树会优先比较 name 来确定下一步应该搜索的方向,往左还是往右。

如果 name 相同的时候再比较 age。

但如果查询条件没有 name,就不知道应该怎么查了,因为 name 是 B+树中的前置条件,没有 name,索引就派不上用场了。


✅ 场景回顾:

我们定义了如下联合索引:

sql 复制代码
INDEX idx_name_age_city(name, age, city)

🧠 Mermaid 决策图:判断是否命中联合索引

此处显示不出来,可以复制在 Obsidian 查看流程图。

flowchart TD A[查询中是否包含 name?] -->|是| B[是否包含 age?] A -->|否| Z1[索引失效❌] B -->|是| C[是否包含 city?] B -->|否| Y1[使用部分索引(name)✅] C -->|是| X1[使用完整索引(name, age, city)✅] C -->|否| Y2[使用部分索引(name, age)✅] Y1 --> END[查询命中部分索引🎯] Y2 --> END X1 --> END Z1 --> END

📝 图示说明:

  • 如果查询语句从 name 开始,后面的字段按顺序出现,就能逐步命中更多的联合索引列。
  • 如果 name 没有出现在 WHERE 中 ,即使用了 agecity,也会 直接索引失效
  • 一旦中间字段断了最左前缀链条 (例如只查 name + city,跳过 age),也只能用到前面那一段。

🚀 最左前缀原则总结口诀:

复制代码
联合索引连着用,断了就失效;
从左到右顺序查,缺谁都不行;
WHERE、ORDER、GROUP 用,记住它最香;
模糊查询 % 开头,索引说拜拜;
相关推荐
zhou185几秒前
MySQL保姆级安装教程(附资源包+5分钟极速配置+环境变量调试技巧)
java·python·mysql·php
TDengine (老段)44 分钟前
基于 TSBS 标准数据集下 TimescaleDB、InfluxDB 与 TDengine 性能对比测试报告
java·大数据·开发语言·数据库·时序数据库·tdengine·iotdb
TDengine (老段)1 小时前
TDengine 在金融领域的应用
大数据·数据库·物联网·金融·时序数据库·tdengine·涛思数据
标贝科技1 小时前
标贝科技:大模型领域数据标注的重要性与标注类型分享
数据库·人工智能
野木香1 小时前
mysql8常用sql语句
数据库·sql·mysql
hycccccch1 小时前
Redis的IO多路复用
数据库·redis·缓存
rylshe13141 小时前
spark sql基本操作
sql·spark
不再幻想,脚踏实地2 小时前
Spring Boot配置文件
java·数据库·spring boot
_extraordinary_2 小时前
MySQL 事务(二)
android·数据库·mysql
rylshe13142 小时前
在scala中sparkSQL连接mysql并添加新数据
开发语言·mysql·scala