当前位置: 首页 > news >正文

联合索引的最左前缀原则与失效场景

文章目录

    • 《联合索引的最左前缀原则与失效场景》
      • 一、前言:索引不总是生效的
      • 二、联合索引的结构
      • 三、最左前缀原则的核心
        • (1)完整匹配(命中索引)
        • (2)前缀匹配(部分命中)
        • (3)仅最左列匹配
        • (4)跳列查询(失效)
      • 四、常见索引失效场景
        • 1. **范围查询(>、<、BETWEEN、LIKE)中断匹配**
        • 2. **模糊匹配前缀失效**
        • 3. **函数操作导致失效**
        • 4. **隐式类型转换失效**
        • 5. **OR 条件混合失效**
        • 6. **计算表达式失效**
      • 五、Explain 实战验证
      • 六、索引设计与优化建议
      • 七、面试高频问题与答题模板
      • 八、总结


《联合索引的最左前缀原则与失效场景》


一、前言:索引不总是生效的

大家好,我是程序员卷卷狗。

我们都知道给字段建索引能提高查询速度,
但很多时候,你明明建了索引,SQL 却依然走全表扫描。

面试官问:

“联合索引的最左前缀原则是什么?”
“为什么有时候用了 LIKE、OR、函数就失效了?”

要答好这个问题,必须先理解:
联合索引的底层结构是有序的前缀匹配树。


二、联合索引的结构

假设我们创建一个三列联合索引:

CREATE INDEX idx_name_age_city ON user(name, age, city);

InnoDB 会在 B+ 树的叶子节点中存储:

(name, age, city, 主键id)

索引的排序方式如下:

先按 name 排序,
name 相同时按 age 排序,
name 和 age 都相同时按 city 排序。

可以理解为一张“有序排列表”

nameagecity
Alice20Beijing
Alice22Shanghai
Bob19Beijing
Bob23Chengdu

三、最左前缀原则的核心

定义:
MySQL 使用联合索引时,会从最左边的索引列开始匹配,
一旦遇到范围查询、模糊匹配或非连续字段,就停止匹配。

(1)完整匹配(命中索引)
WHERE name='Alice' AND age=20 AND city='Beijing'

命中三列,索引完全使用。

(2)前缀匹配(部分命中)
WHERE name='Alice' AND age=20

命中前两列,仍能使用索引。

(3)仅最左列匹配
WHERE name='Alice'

命中第一列,索引可用。

(4)跳列查询(失效)
WHERE age=20 AND city='Beijing'

name 被跳过,索引无法命中。

规则总结:

  • 从左向右连续匹配;
  • 一旦中断,后续字段无法使用。

四、常见索引失效场景

1. 范围查询(>、<、BETWEEN、LIKE)中断匹配
WHERE name='Alice' AND age>20 AND city='Beijing';
  • name 精确匹配 ;
  • age 为范围匹配(>20);
  • city 失效。

范围条件之后的字段不再使用索引。


2. 模糊匹配前缀失效
WHERE name LIKE '%lice';

无法利用索引(前缀未知)。

WHERE name LIKE 'A%';

能利用索引(前缀已知)。


3. 函数操作导致失效
WHERE LEFT(name,3)='Ali';

索引失效,因为函数作用在列上。

改写方式:

WHERE name LIKE 'Ali%';

4. 隐式类型转换失效
WHERE age = '20';

若 age 为 INT,而 ‘20’ 为字符串,会发生隐式转换:

CAST(age AS CHAR) = '20';

索引失效。

改写:

WHERE age = 20;

5. OR 条件混合失效
WHERE name='Alice' OR city='Beijing';

若 city 未建立独立索引,则整体失效。

改写:

  • 为 city 单独建索引;
  • 或用 UNION ALL 拆分查询。

6. 计算表达式失效
WHERE age + 1 = 20;

索引失效,因为表达式作用在列上。

改写:

WHERE age = 19;

五、Explain 实战验证

假设表结构:

CREATE TABLE user (id INT PRIMARY KEY,name VARCHAR(20),age INT,city VARCHAR(20),INDEX idx_name_age_city (name, age, city)
);
SQL结果Extra
SELECT * FROM user WHERE name='Alice';索引生效Using index condition
SELECT * FROM user WHERE name='Alice' AND age>20;部分命中Using index condition
SELECT * FROM user WHERE age=20;索引失效Using where
SELECT * FROM user WHERE name LIKE 'A%';索引生效Using index condition
SELECT * FROM user WHERE name LIKE '%A';失效Using where
SELECT * FROM user WHERE name='Alice' AND age=20 AND city='Beijing';完全命中Using index

六、索引设计与优化建议

设计策略原则说明
① 建联合索引时把区分度高的字段放前面提升过滤率
② WHERE、ORDER BY、GROUP BY 常用字段放在前缀位置利用最左原则
③ 尽量避免函数、计算、类型转换防止优化器放弃索引
④ 模糊匹配尽量使用后缀 % 而非前缀 %支持前缀匹配
⑤ 使用 EXPLAIN 验证索引命中情况判断 type、key、Extra

七、面试高频问题与答题模板

问题答案要点
Q1:什么是最左前缀原则?联合索引按定义顺序匹配字段,从最左开始连续使用。
Q2:为什么范围查询会导致后续字段失效?因为 B+Tree 有序性被破坏,无法继续匹配。
Q3:LIKE ‘%xx’ 能用索引吗?不能,前缀未知。
Q4:为什么函数会导致索引失效?函数在列上操作,破坏原索引值。
Q5:OR 条件一定导致失效吗?若两侧字段都有索引则不会,否则整体失效。
Q6:如何验证索引是否命中?使用 EXPLAIN 查看 key 与 Extra 字段。

八、总结

联合索引的本质是一棵按列顺序排列的有序 B+ 树。
最左前缀原则,是优化器决定是否能使用索引的根规则。

一句话记住:

匹配从左开始,遇“断”即停。

掌握这一原则,你不仅能解释索引失效的原因,
还能主动在表设计和 SQL 编写中“避坑提速”。

下一篇(第 9 篇),我将写——
《索引优化策略:高效建索引的 7 条实战准则》
总结从索引区分度、联合索引布局、覆盖索引设计到业务性能调优的完整策略。


http://www.dtcms.com/a/593076.html

相关文章:

  • solidity中的抽象合约
  • 去中心化铸就价值基石:CVC与BTC引领区块链投资新范式
  • 微美全息(NASDAQ:WIMI)基于边缘云计算与区块链的数据缓存算法,引领数据管理变革
  • K8S RD: Kubernetes核心概念与故障排查全解析
  • 响应式网站手机端广州网站建设商城建设
  • 第三方应用软件提权之vnc提权
  • iOS 跨平台开发实战指南,从框架选择到开心上架(Appuploader)跨系统免 Mac 发布全流程解析
  • 【Go】并发编程的核心思想 CSP 模型
  • 《Vue项目开发实战》第四章:组件封装--ToolBar
  • Redis拒绝策略
  • iphone Delta模拟器如何从夸克网盘导入游戏ROM 附游戏资源下载
  • 专业网站建设平台网站建设功能评估表
  • 做农业网站怎么赚钱58同城北京网站建设
  • 如何在命令行中调用Dev-C++的编译器?
  • C语言自定义类型:联合体与枚举
  • 在线网站推广工具WordPress 付费下载阅读
  • Windows2008 如何禁用FSO?
  • 了解一下LSTM:长短期记忆网络(改进的RNN)
  • 【微服务 - easy视频 | day03】服务与服务之间的调用
  • 网站建设定做mvc网站建设的实验报告
  • CMP(类Cloudera CMP 7 404版华为Kunpeng)告别CDH/CDP,拥抱自主可控的新时代
  • 生成ios钱包pkpass文件
  • Paimon——官网阅读:理解文件
  • 做网站应该学什么语言网站建设裕鸿国际
  • Xenium数据分析 | 使用Xenium Ranger重新分析数据
  • MySQL 8.0 新特性详解:窗口函数,开启数据分析的潘多拉魔盒
  • 基于模板匹配的数字和大写字母识别(Matlab)
  • 网站编程赚钱企业门户网站 php
  • 网站有什么到期网站空间哪里买
  • LeetCode 分类刷题:2816. 翻倍以链表形式表示的数字