MySQL最左匹配原则,道儿上兄弟都得知道的原则,从思维图到基础再到深入

比如索引abc_index:(a,b,c)是a,b,c三个字段的联合索引,下列sql执行时都无法命中索引abc_index;

select * from table where c = ‘1’;

select * from table where b =‘1’ and c =‘2’;

以下三种情况却会走索引:

select * from table where a = ‘1’;

select * from table where a = ‘1’ and b = ‘2’;

select * from table where a = ‘1’ and b = ‘2’ and c=‘3’;

从上面两个例子大家有木有看出点眉目呢?

是的,索引abc_index:(a,b,c),只会在where条件中带有(a)、(a,b)、(a,b,c)的三种类型的查询中使用。其实这里说的有一点歧义,其实当where条件只有(a,c)时也会走,但是只走a字段索引,不会走c字段。

那么这都是为什么呢?我们一起来看看其原理吧。

一、最左匹配原则的原理

==========================================================================

MySQL 建立多列索引(联合索引)有最左匹配的原则,即最左优先:

如果有一个 2 列的索引 (a, b),则已经对 (a)、(a, b) 上建立了索引;

如果有一个 3 列索引 (a, b, c),则已经对 (a)、(a, b)、(a, b, c) 上建立了索引;

假设数据 表 LOL (id,sex,price,name) 的物理位置(表中的无序数据)如下:

(注:下面数据是测试少量数据选用的,只为了方便大家看清楚。实际操作中,应按照使用频率、数据区分度来综合设定索引顺序喔~)

主键id sex(a) price(b) name©

(1) 1 1350 AAA安妮

(2) 2 6300 MMM盲僧

(3) 1 3150 NNN奈德丽

(4) 2 6300 CCC锤石

(5) 1 6300 LLL龙女

(6) 2 3150 EEE伊泽瑞尔

(7) 2 6300 III艾克

(8) 1 6300 BBB暴走萝莉

(9) 1 4800 FFF发条魔灵

(10) 2 3150 KKK卡牌大师

(11) 1 450 HHH寒冰射手

(12) 2 450 GGG盖伦

(13) 2 3150 OOO小提莫

(14) 2 3150 DDD刀锋之影

(15) 2 6300 JJJ疾风剑豪

(16) 2 450 JJJ剑圣

当你在LOL表创建一个联合索引 abc_index:(sex,price,name)时,生成的索引文件逻辑上等同于下表内容(分级排序)

sex(a) price(b) name© 主键id

1 450 HHH寒冰射手 (11)

1 1350 AAA安妮 (1)

1 3150 NNN奈德丽 (3)

1 4800 FFF发条魔灵 (9)

1 6300 BBB暴走萝莉 (8)

1 6300 LLL龙女 (5)

2 450 GGG盖伦 (12)

2 450 JJJ剑圣 (16)

2 3150 DDD刀锋之影 (14)

2 3150 EEE伊泽瑞尔 (6)

2 3150 KKK卡牌大师 (10)

2 3150 OOO小提莫 (13)

2 6300 CCC锤石 (4)

2 6300 III艾克 (7)

2 6300 JJJ疾风剑豪 (15)

2 6300 MMM盲僧 (2)

小伙伴儿们有没有发现B+树联合索引的规律?感觉还有点模糊的话,那咱们再来看一张索引存储数据的结构图,或许更明了一些。

在这里插入图片描述

这是一张来自思否上的图片,层次感很清晰,小伙伴可以看到,对于B+树中的联合索引,每级索引都是排好序的。联合索引 bcd_index:(b,c,d) , 在索引树中的样子如图 , 在比较的过程中 ,先判断 b 再判断 c 然后是 d 。

由上图可以看出,B+ 树的数据项是复合的数据结构,同样,对于我们这张表的联合索引 (sex,price,name)来说 ,B+ 树也是按照从左到右的顺序来建立搜索树的,当SQL如下时:

select sex,price,name from LOL where sex = 2 and price = 6300 and name = ‘JJJ疾风剑豪’;

B+ 树会优先比较 sex 来确定下一步的指针所搜方向,如果 sex 相同再依次比较 price 和 name,最后得到检索的数据;

二、违背最左原则导致索引失效的情况

================================================================================

(下面以联合索引 abc_index:(a,b,c) 来进行讲解,便于理解)

1、查询条件中,缺失优先级最高的索引 “a”

where b = 6300 and c = 'JJJ疾风剑豪' 这种没有以 a 为条件来检索时;B+树就不知道第一步该查哪个节点,从而需要去全表扫描了(即不走索引)。因为建立搜索树的时候 a 就是第一个比较因子,必须要先根据 a 来搜索,进而才能往后继续查询b 和 c,这点我们通过上面的存储结构图可以看明白。

2、查询条件中,缺失优先级居中的索引 “b”

当 where a =1 and c =“JJJ疾风剑豪” 这样的数据来检索时;B+ 树可以用 a 来指定第一步搜索方向,但由于下一个字段 b 的缺失,所以只能把 a = 1 的数据主键ID都找到,通过查到的主键ID回表查询相关行,再去匹配 c = ‘JJJ疾风剑豪’ 的数据了,当然,这至少把 a = 1 的数据筛选出来了,总比直接全表扫描好多了。

这就是MySQL非常重要的原则,即索引的最左匹配原则。

三、查询优化器偷偷干了哪些事儿

==============================================================================

当对索引中所有列通过"=" 或 “IN” 进行精确匹配时,索引都可以被用到。

1、如果建的索引顺序是 (a, b)。而查询的语句是 where b = 1 AND a = ‘陈哈哈’; 为什么还能利用到索引?

理论上索引对顺序是敏感的,但是由于 MySQL 的查询优化器会自动调整 where 子句的条件顺序以使用适合的索引,所以 MySQL 不存在 where 子句的顺序问题而造成索引失效。当然了,SQL书写的好习惯要保持,这也能让其他同事更好地理解你的SQL。

2、还有一个特殊情况说明下,下面这种类型的SQL, a 与 b 会走索引,c不会走。

select * from LOL where a = 2 and b > 1000 and c=‘JJJ疾风剑豪’;

对于上面这种类型的sql语句;mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配(包括like '陈%'这种)。在a、b走完索引后,c已经是无序了,所以c就没法走索引,优化器会认为还不如全表扫描c字段来的快。所以只使用了(a,b)两个索引,影响了执行效率。

其实,这种场景可以通过修改索引顺序为 abc_index:(a,c,b),就可以使三个索引字段都用到索引,建议小伙伴们不要有问题就想着新增索引哦,浪费资源还增加服务器压力。

综上,如果通过调整顺序,就可以解决问题或少维护一个索引,那么这个顺序往往就是我们DBA人员需要优先考虑采用的。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

完结

Redis基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。Redis是如今互联网技术架构中,使用最广泛的缓存,在工作中常常会使用到。Redis也是中高级后端工程师技术面试中,面试官最喜欢问的问题之一,因此作为Java开发者,Redis是我们必须要掌握的。

Redis 是 NoSQL 数据库领域的佼佼者,如果你需要了解 Redis 是如何实现高并发、海量数据存储的,那么这份腾讯专家手敲《Redis源码日志笔记》将会是你的最佳选择。

edis基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。Redis是如今互联网技术架构中,使用最广泛的缓存,在工作中常常会使用到。Redis也是中高级后端工程师技术面试中,面试官最喜欢问的问题之一,因此作为Java开发者,Redis是我们必须要掌握的。

Redis 是 NoSQL 数据库领域的佼佼者,如果你需要了解 Redis 是如何实现高并发、海量数据存储的,那么这份腾讯专家手敲《Redis源码日志笔记》将会是你的最佳选择。

[外链图片转存中…(img-DRm9xlk5-1711947023329)]

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值