码迷,mamicode.com
首页 > 其他好文 > 详细

索引在什么情况下遵循最左前缀的规则?

时间:2019-12-26 10:02:19      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:就是   table   char   strong   技术   系统工具   很多   info   遇到   

在创建一个n列的索引时,需要遵循“最左前缀”原则。

创建表:create table abc(a varchar(32) not null, b varchar(32), c date );

创建普通索引:create index in_abc_acb on abc(a, c, b);

1、select * from abc where b=‘bbb‘ and c=sysdate;  不会用到索引,必须要用到左边第一个字段;

2、select * from abc where a like ‘1%‘ and c=sysdate;  a 会用到索引,c 则不会,遇到范围(>、<、between、like)查询就停止匹配;

3、select * from abc where trim(a) = ‘a‘ ; 不会用到索引 ,字段前加了函数(表达式)索引会被抑制。where a = ‘a‘ and c + 1 > sysdate,c不会用到索引,而where a = ‘a‘ and c > sysdate - 2,会用到索引;

4、select * from abc where b like ‘b%‘ and c = sysdate and a=‘a‘ ;acb的索引都可以用到,因为索引是从左到右匹配,in 和 = 可以乱序;

 

索引的最左前缀原理:

通常我们在建立联合索引的时候,也就是对多个字段建立索引,相信建立过索引的同学们会发现,无论是oralce还是mysql都会让我们选择索引的顺序,比如我们想在a,b,c三个字段上建立一个联合索引,我们可以选择自己想要的优先级,a、b、c,或者是b、a、c 或者是c、a、b等顺序。为什么数据库会让我们选择字段的顺序呢?不都是三个字段的联合索引么?这里就引出了数据库索引的最左前缀原理。

比如:索引index1:(a,b,c)有三个字段,我们在使用sql语句来查询的时候,会发现很多情况下不按照我们想象的来走索引。

 

select * from table where c = ‘1‘

这个sql语句是不会走index1索引的

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

这个语句也不会走index1索引。

什么语句会走index1索引呢?

 

答案是:

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‘

我们可以发现一个共同点,就是所有走索引index1的sql语句的查询条件里面都带有a字段,那么问题来了,index1的索引的最左边的列字段是a,是不是查询条件中包含a就会走索引呢?

例如:

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

这个sql语句,按照之前的理解,包含a字段,会走索引,但是是不是所有字段都走了索引呢?

我们来做个实验:

我这里有一个表:

技术图片

建立了一个联合索引,prinIdAndOrder里面有三个字段  PARENT_ID, MENU_ORDER, MENU_NAME

接下来测试之前的语句:

技术图片
EXPLAIN
SELECT 
  t.* 
FROM
  sys_menu t 
WHERE t.`PARENT_ID` = ‘0‘ 
  AND t.`MENU_NAME` = ‘系统工具‘
技术图片

这一句sql就相当于之前的select * from table where a = ‘1‘ and c= ‘2’这个sql语句了,我们来看看解释计划:

技术图片

可以看到走了索引prinIdAndOrder,但是旁边的key_len=303,但道理key_len应该是大于303的,为什么呢?因为PARENT_ID字段的类型是varchar(100) NULL,所以key_len=100*3+2+1=303,但是还有MENU_NAME呢!具体的key_len的计算方法,大家可以百度,我的表的字符集是utf-8,不同字符集的表的计算方式不一样。这里的解释计划显示key_len只有303,说明只是走了字段PARENT_ID的索引,没有走MENU_NAME的索引。

这也是最左前缀原理的一部分,索引index1:(a,b,c),只会走a、a,b、a,b,c 三种类型的查询,其实这里说的有一点问题,a,c也走,但是只走a字段索引,不会走c字段。

另外还有一个特殊情况说明下,select * from table where a = ‘1‘ and b > ‘2’  and c=‘3‘ 这种类型的也只会有a与b走索引,c不会走。

像select * from table where a = ‘1‘ and b > ‘2’  and c=‘3‘ 这种类型的sql语句,在a、b走完索引后,c肯定是无序了,所以c就没法走索引,数据库会觉得还不如全表扫描c字段来的快。不知道我说明白没,感觉这一块说的始终有点牵强。

索引在什么情况下遵循最左前缀的规则?

标签:就是   table   char   strong   技术   系统工具   很多   info   遇到   

原文地址:https://www.cnblogs.com/Rivend/p/12099975.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!