最左前缀原则

最左前缀原则个人分析

前言

​ 网上看了无数篇有关最左前缀原则的分析了,有结合b+树分析底层数据结构的,也有直接上例子EXPLAIN来分析的。但不管怎么去理解,总是有人会提到一些有争议的问题,比如联合索引(a,b,c)为什么在条件语句为“a=1 and b>2 and c=3”不去走联合索引。。。等等等等。。。

​ 所以呢,本菜鸡就结合实际案例再加上自己对于b+树的一些理解,谈谈我个人的看法吧QAQ~

工具:MySQL 8.0+Navicat 12

基础表结构

借用Navicat建立一个test表结构如下:
在这里插入图片描述

`a`是主键,其中有一些冗余字段是我个人用来学习用的,主要关注`a``b``c``name1`这四个字段就好啦

顺带也瞟一眼我那随心所欲的数据~
在这里插入图片描述

有了基础的表结构,先直接上手分析一波

实践分析

这里我们主要对以下几个内容进行分析:

  • 建立包含主键字段的联合索引(a,b,c),分析该种情况下的联合索引
  • 建立不包含主键字段的联合索引(b,c,name1),(内心OS:虽然看起来很别扭,但是别扭也是一种加深印象的方式嘛hhh)分析该种情况下的联合索引

联合索引(a,b,c)

字段a:varchar(20),主键,不为NULL 字段b:varchar(30),可为NULL 字段c:varchar(40),可为NULL

#建立索引
ALTER TABLE test ADD KEY idx_key1(a,b,c);

此时,在表的索引结构中可以看到新增了如下一行:

在这里插入图片描述

  • 首先我们执行SQL语句EXPLAIN SELECT * FROM test WHERE a='1';

    可以理解的是,对于联合索引(a,b,c),诸如:

    where a = '1'
    where a = '1' and b = '1'
    where a = '1' and b = '1' and c = '1'
    

    这三种条件语句会走联合索引。

    那么问题来了,当我们联合索引(a,b,c)中a字段为主键时,MySQL是会选择采用Primary key的索引方式呢?还是采用我们的联合索引idx_key1的索引方式呢?

    在这里插入图片描述

    分析执行结果可知,在possible_keys中虽然列出了两种索引,但实际采用的key还是我们的Primary key这是因为,在我们的查询语句中,一旦索引命中了主键,此时仅需要索引一次就能找到,那么MySQL就不会再进行复杂的扫描。而且也可以看到对应的type为const,说明在对主键a进行条件查询时,MySQL已经将其转化成了一个常量,表示此时我们的表中仅有唯一的匹配行,此时,仅需要读取1次就可以查询到,效率是非常高的。

    附:type字段和key_len字段的含义:

    • type:表示访问类型。访问类型有很多,这个建议自己去了解下吧。
    • key_len:索引长度的字节数,常用来分析是否走联合索引。utf8的情况下:char对应×3,var对应可变+2,可以为NULL又需要+1字节的标记。所以这里的key_len=20*3+2+1=63。
  • 接下来我们再试试另外两种情况where a = '1' and b = '1'where a = '1' and b = '1' and c = '1'

    执行where a = '1' and b = '1'之后:

    在这里插入图片描述

    执行where a = '1' and b = '1' and c = '1'之后:

    在这里插入图片描述

    从图中可见:这两种情况完美符合我们之前对于为什么走Primary key的分析。

联合索引(b,c,name1)

字段b:varchar(30),可为NULL 字段c:varchar(40),可为NULL 字段name1:varchar(20),可为NULL

为了避免之前建立的索引的影响,我们将其删除之后重新建立一个联合索引。

#重新建立索引
ALTER TABLE test ADD KEY idx_key1(b,c,name1);

此时,去表中的索引结构中验证一下:

在这里插入图片描述

  • 为了对应上面的联合索引,我们还是选择先执行SQL语句EXPLAIN SELECT * FROM test WHERE b='1';

    在这里插入图片描述

  • 再执行EXPLAIN SELECT * FROM test WHERE b='1' and c='1';

    在这里插入图片描述

  • 再执行EXPLAIN SELECT * FROM test WHERE b='1' and c='1' and name1='a';

    在这里插入图片描述

    实验结果都完美符合我们对于联合索引的理解,当然为了加深一下,我们试一下如下几个条件语句的情况:

    where b='1' and name1='a'
    

    在这里插入图片描述

    ​ 这时候发现只会用到b='1'的索引,却没有使用name1='a'的索引。这是因为,在B+树的叶子节点中,根据b='1'索引是可以确定字段c的排序顺序的,但是当我们需要使用c进行索引时,发现缺失了等值条件c = '${value}'那么MySQL在c的排序中就会进行部分全表扫描,所以此时name1='a'也就自然而然无法走索引了。

    where c='1' and name1='a'
    

    在这里插入图片描述

    ​ 这里为什么走全表扫描其实也是上述的原理,只不过缺失的等值条件b = '${value}'直接是联合索引的最左字段罢了。条件where name1 = 'a'的情况也是同理哦~

    #通配符的位置
    where b like '%'
    

    ​ 只要通配符在字符的最前面,都会使索引失效

    where b like '1%'
    

    在这里插入图片描述

    ​ 只要通配符在字符的最前面,都会使索引失效

    where b like '1%'
    

    在这里插入图片描述

    ​ 通配符在后面,索引还是可以生效的~

总结

​ 其实理解了B+树原理之后,对于最左前缀原则的理解是有非常大的帮助的,每次分析效率或者是否走索引的时候,都可以在脑海里建立一颗简易的B+树,模拟一下过程就可以啦~

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值