crossoverJie / JCSprout

👨‍🎓 Java Core Sprout : basic, concurrent, algorithm
https://crossoverjie.top/JCSprout
MIT License
27.07k stars 7.09k forks source link

SQL优化-最左匹配原则疑问 #162

Open wcjinzita opened 5 years ago

wcjinzita commented 5 years ago

https://github.com/crossoverJie/JCSprout/blob/master/MD/SQL-optimization.md 在上面这个地址中,针对SQL优化的专题,其中针对“最左匹配原则”的介绍,有点歧义,我在这里给订正一下,你看一下是否合适?

问题描述:

如果给 user 表中的 username pwd 字段创建了复合索引那么使用以下SQL 都是可以命中索引:

select username from user where username='zhangsan' and pwd ='axsedf1sd'

select username from user where pwd ='axsedf1sd' and username='zhangsan'

select username from user where username='zhangsan' 但是使用

select username from user where pwd ='axsedf1sd' 是不能命中索引的。

此处,如果单独使用pwd字段,是可以用到索引的。

讲上面问题之前,我先补充一些知识,因为我觉得你对索引理解是狭隘的: 上述你的pwd条件查询的explain结果中显示用到索引的情况类型是不一样的。,可观察explain结果中的type字段。你的查询是:

  1. type: index

解释: index:这种类型表示是mysql会对整个该索引进行扫描。要想用到这种类型的索引,对这个索引并无特别要求,只要是索引,或者某个复合索引的一部分,mysql都可能会采用index类型的方式扫描。但是呢,缺点是效率不高,mysql会从索引中的第一个数据一个个的查找到最后一个数据,直到找到符合判断条件的某个索引。

所以,对于你的第一条语句: EXPLAIN select username from user where pwd ='axsedf1sd';

判断条件是pwd ='axsedf1sd',而pwd是(user_name, pwd)复合索引的一部分,没有问题,可以进行index类型的索引扫描方式。explain显示结果使用到了索引,是index类型的方式。

准确一点说,是没有完全用到复合索引,但是会使用一部分,所以也是走索引的。

wbontheway commented 3 years ago

索引覆盖的情况下,like'%%'也会走索引。 但是效率不高,个人觉得有点杠了