一起来探索联合索引吧~

这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

说到联合索引,一定会谈论到最左匹配原则。最左原则指的就是如果你的SQL语句中用到了联合索引中的最左边的索引,那么这条SQL语句就可以利用这个联合索引去进行匹配,值得注意的是,当遇到范围查询(>、<、between、like)就会停止匹配

假设,我们对(a,b)字段建立一个索引,当我们执行

select * from t where a = 1;

或者

select * from t where a = 1 and b = 2;
复制代码

是可以用到索引的,不仅如此,如果执行

select * from t where b = 2 and a = 1;

复制代码

也是会用到索引的,因为优化器会帮我们调整a,b的位置和索引顺序一致。

但是,如果

select * from t where b = 2;

复制代码

则不会用到索引,为什么呢?

因为引擎在简历索引的时候,是按照索引从左到右顺序来建立索引的,比如我们创建索引(a,b)后,B+树会优先比较a列来确定下一步的搜索方向,如果a列相同再一次比较b列。看下图,我们会发现索引树上,a是有序的,b列是无序的。

截屏2021-11-16 下午11.43.49.png

所以回到上面那句sql,我们可以看到检索条件没有a列,所以b+树上就不知道该查哪个节点,因为搜索树的时候a列是第一个比较因子,必须先根据a列来搜索才能知道下一步去哪里搜索。只有当a确定等于某个值的时候,b相对来说才是有序的。 比如说a = 1,那么 b 为 1和2,呈递增状态。但如果a是个范围的话,比如说a > 1,那 b 就会是 1,2,1,4,1,2,很显然无序。

当我们对(a,b,c,d)简历索引,执行

select * from t where a = 1 and b = 2 and c > 3 and d = 4 ;

复制代码

那么只有a,b,c可以用到索引,d用不到,为什么呢,因为d前面遇到了范围查询!!!!!!!!!太可怕啦!!!!!c > 3 简直就是毒瘤!因为c是不确定的,所以在这个范围里d也不是有序的。

接下来考大家几条sql如何建立索引。和大家说个小技巧,就是按照索引简历顺序一个个往后对,遇到范围,那范围后面的将是无效的。

第一题:

SELECT * FROM table WHERE a = 1 and b = 2 and c = 3; 
复制代码

答案是 (a,b,c)或者(c,b,a)或者(b,a,c)都可以,重点要的是将区分度高的字段放在前面,区分度低的字段放后面。例如假设区分度由大到小为b,a,c。那么我们就对(b,a,c)建立索引。在执行sql的时候,优化器会帮我们调整where后a,b,c的顺序,让我们用上索引。

第二题:

SELECT * FROM table WHERE a > 1 and b = 2; 
复制代码

答案是 对(b,a)建立索引。如果你建立的是(a,b)索引,那么只有a字段能用得上索引,毕竟最左匹配原则遇到范围查询就停止匹配。如果对(b,a)建立索引那么两个字段都能用上,优化器会帮我们调整where后a,b的顺序,让我们用上索引。

第三题:

SELECT * FROM `table` WHERE a > 1 and b = 2 and c > 3; 
复制代码

答案是 (b,a)或者(b,c)都可以,要结合具体情况具体分析。

第四题:

SELECT * FROM `table` WHERE a = 1 ORDER BY b;
复制代码

答案是 对(a,b)建索引,当a = 1的时候,b相对有序,可以避免再次排序!结合创建b+树的过程就会知道为啥了。

第五题:

SELECT * FROM `table` WHERE a IN (1,2,3) and b > 1; 
复制代码

答案是 对(a,b)建立索引,因为IN在这里可以视为等值引用,不会中止索引匹配,所以还是(a,b)!

猜你喜欢

转载自juejin.im/post/7031196229451120671