MySQL索引最左原则:从原理到实战的深度解析

一、什么是索引最左原则?

索引最左原则是MySQL复合索引使用的核心规则,简单来说:

"当使用复合索引(多列索引)时,查询条件必须从索引的最左列开始,且不能跳过中间的列,否则索引将无法完全生效"

为什么会有这个原则?

这与B+树索引的存储结构密切相关:

  1. 复合索引按照定义时的列顺序构建
  2. 数据先按第一列排序
  3. 第一列相同的情况下按第二列排序
  4. 依此类推形成层级结构

二、3种典型场景分析

场景1:完美匹配索引顺序

-- 创建索引
CREATE INDEX idx_user ON users(country, city, age); -- 有效查询
SELECT * FROM users
WHERE country='China'
AND city='Beijing'
AND age=30;

索引使用情况:同时使用三列进行精确查找,走全索引扫描

场景2:缺少最左列

-- 无效查询
SELECT * FROM users
WHERE city='Shanghai'
AND age=25;

索引失效原因:没有最左列country,无法利用索引的排序结构

场景3:中间断档查询

-- 部分有效查询
SELECT * FROM users
WHERE country='USA'
AND age=28;

️ 索引使用情况:仅使用country列进行索引查找,age列无法参与索引过滤

三、5大实战案例分析

案例1:范围查询后的列失效

SELECT * FROM users
WHERE country='Japan'
AND city > 'Osaka'
AND age=35;

索引使用:仅使用到country和city列,age列无法走索引过滤

案例2:LIKE模糊查询

-- 有效情况
SELECT * FROM users
WHERE country='China'
AND city LIKE 'Bei%'; -- 失效情况
SELECT * FROM users
WHERE city LIKE '%hai';

规律总结:只有最左前缀的LIKE查询能使用索引

案例3:覆盖索引特例

-- 查询字段全在索引中
SELECT country, city, age
FROM users
WHERE city='Guangzhou';

特殊机制:虽然不符合最左原则,但通过索引扫描(Index Scan)而非索引查找(Index Seek)完成查询

案例4:排序优化

-- 有效排序
SELECT * FROM users
ORDER BY country, city, age; -- 失效排序
SELECT * FROM users
ORDER BY city, age;

排序规则:ORDER BY子句同样需要遵循最左原则

案例5:索引跳跃扫描(MySQL 8.0+)

-- MySQL 8.0新特性
SELECT * FROM users
WHERE city='Paris'
AND age=30;

优化机制:通过Index Skip Scan技术突破传统限制,但需要满足:

  • 前导列不同值较少
  • 优化器认为扫描成本更低

四、最佳实践指南

  1. 索引设计原则
  • 将高区分度的列放在左侧
  • 频繁组合查询的列优先
  • 避免创建超过3列的复合索引
  1. 查询优化技巧
-- 反模式
SELECT * FROM table WHERE col2=1 AND col3=2; -- 优化方案
ALTER TABLE table ADD INDEX idx_col1_col2_col3(col1, col2, col3);
SELECT * FROM table WHERE col1=1 AND col2=1 AND col3=2;

索引分析工具 使用EXPLAIN查看索引使用情况:

EXPLAIN SELECT * FROM users WHERE country='China' AND age=25;

五、常见误区解析

误区1:所有列单独建索引更好

CREATE INDEX idx_country ON users(country);
CREATE INDEX idx_city ON users(city);
CREATE INDEX idx_age ON users(age);

错误认知:

正确做法:分析实际查询模式,建立合适的复合索引

误区2:索引顺序无关紧要

CREATE INDEX idx_city_country ON users(city, country);

错误示例:

正确理解:索引顺序直接影响查询效率,需按查询条件频率排序

误区3:所有查询都能走索引

SELECT * FROM users WHERE city LIKE '%York%';

错误期待:

现实情况:非最左前缀的LIKE查询无法使用索引

六、工具推荐

dblens索引分析工具 提供:

  • 可视化索引使用分析
  • AI索引设计分析
  • 智能索引优化建议

    终极口诀:

复合索引像电话,国家城市区号不能差

最左原则要记牢,跳过中间就抓瞎

范围查询是杀手,排序分组也看它

新版优化虽强大,基础规则不能垮

MySQL索引最左原则:从原理到实战的深度解析的更多相关文章

  1. mysql 索引最左原则原理

    索引本质是一棵B+Tree,联合索引(col1, col2,col3)也是. 其非叶子节点存储的是第一个关键字的索引,而叶节点存储的则是三个关键字col1.col2.col3三个关键字的数据,且按照c ...

  2. MySQL索引最左原则

    通过实例理解单列索引.多列索引以及最左前缀原则 实例:现在我们想查出满足以下条件的用户id: 因为我们不想扫描整表,故考虑用索引. 单列索引: ALTER TABLE people ADD INDEX ...

  3. Mysql索引最左匹配原则

    先来看个例子: 1. 示例1:假设有如下的一张表: DROP TABLE IF EXISTS testTable; CREATE TABLE testTable ( ID BIGINT NOT NUL ...

  4. MySQL索引之数据结构及算法原理

    MySQL索引之数据结构及算法原理 MySQL支持多个存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.本文只关注BTre ...

  5. 并发编程(十五)——定时器 ScheduledThreadPoolExecutor 实现原理与源码深度解析

    在上一篇线程池的文章<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中从ThreadPoolExecutor源码分析了其运行机制.限于篇幅,留下了Scheduled ...

  6. 并发编程(十二)—— Java 线程池 实现原理与源码深度解析 之 submit 方法 (二)

    在上一篇<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中提到了线程池ThreadPoolExecutor的原理以及它的execute方法.这篇文章是接着上一篇文章 ...

  7. 【转】mysql索引最左匹配原则的理解

    作者:沈杰 链接:https://www.zhihu.com/question/36996520/answer/93256153 来源:知乎 CREATE TABLE `student` ( `id` ...

  8. mysql索引最左匹配原则的理解

    CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `ci ...

  9. 【转】Mysql索引最左匹配原则理解

    作者:沈杰 链接:https://www.zhihu.com/question/36996520/answer/93256153来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  10. MySQL索引背后的数据结构及原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

随机推荐

  1. JDK 18 最新动态和 JDK 19 新特性预测

    JDK 18 最新动态和 JDK 19 新特性预测_语言 & 开发_Michael Redlich_InfoQ精选文章 里面提到文章 定界延续(delimited continuations) ...

  2. Netty内存池泄漏问题

    为了提升消息接收和发送性能,Netty针对ByteBuf的申请和释放采用池化技术,通过PooledByteBufAllocator可以创建基于内存池分配的ByteBuf对象,这样就避免了每次消息读写都 ...

  3. JVM实战—2.JVM内存设置与对象分配流转

    大纲 1.JVM内存划分的原理细节 2.对象在JVM内存中如何分配如何流转 3.部署线上系统时如何设置JVM内存大小 4.如何设置JVM堆内存大小 5.如何设置JVM栈内存与永久代大小 6.问题汇总 ...

  4. Qt/C++地图标注点的添加删除移动旋转/指定不同图标和动图/拿到单击信号

    一.前言说明 标注点在地图开发中是最常见的应用场景之一,比如在地图上需要显示设备的位置,基本上都是添加标注点,指定图片和尺寸已经经纬度坐标位置.这个功能在每种地图内核中都提供的,这个并没有任何难点,在 ...

  5. Qt音视频开发35-左右通道音量计算和音量不同范围值的转换

    一.前言 视频文件一般会有两个声音通道及左右声道,值有时候一样有时候不一样,很多场景下我们需要对其分开计算不同的音量值,在QAudioFormat中可以获取具体有几个通道,如果是一个通道,则左右通道值 ...

  6. 关于Qt选择qml还是widget的深度思考

    在Qt界始终有两大阵营产生激烈的纷争,那就是选用qml还是widget好,大量初学者也会问这个问题,有以下几点总结. widget属于传统界面开发,和VB/VC/Delphi等拖曳控件开发类似,走CP ...

  7. SpringBoot集成swagger后出现: Failed to start bean ‘documentationPluginsBootstrapper‘的解决方法

    SpringBoot集成swagger后出现: Failed to start bean 'documentationPluginsBootstrapper'的编译错误: org.springfram ...

  8. 尝试 vmware 16.0.0 过虚拟化 过xf虚拟机检测

    前言 最新想在vmware虚拟机上玩xf,网上找了不少教程,于是打算自己尝试下. 如果可以修改成功的话,其价值嘛不可估量. 环境 vmware版本是16.0.0,已安装VMware Tools vmw ...

  9. 前端(四)-jQuery

    1.jQuery的基本用法 1.1 jQuery引入 <script src="js/jquery-3.4.1.min.js" type="text/javascr ...

  10. 利用bash脚本函数执行创建用户和组,并设置sudo权限等

    示例:利用bash脚本函数执行创建用户和组,并设置sudo权限等: Linux服务器设置历史命令记录,及命令执行的时间: sudo echo 'HISTTIMEFORMAT="%F %T w ...