在MySQL中进行SQL优化的时候,常常会在一些状况下,对MySQL可否利用索引有一些迷惑。html
譬如:mysql
今天,我将会用一个模型,把这些问题都一一解答,让你对MySQL索引的使用再也不畏惧sql
EXPLAIN执行计划中有一列 key_len 用于表示本次查询中,所选择的索引长度有多少字节,一般咱们可借此判断联合索引有多少列被选择了。数据库
在这里 key_len 大小的计算规则是:ide
首先很是感谢登博,给了我一个很好的启发,我经过他的文章,而后结合本身的理解,制做出了这幅图优化
乍一看,是否是很晕,不急,咱们慢慢来看ui
图中一共分了三个部分:this
咱们细细展开。spa
Index Key是用来肯定MySQL的一个扫描范围,分为上边界和下边界。3d
MySQL利用=、>=、> 来肯定下边界(first key),利用最左原则,首先判断第一个索引键值在where条件中是否存在,若是存在,则判断比较符号,若是为(=,>=)中的一种,加入下边界的界定,而后继续判断下一个索引键,若是存在且是(>),则将该键值加入到下边界的界定,中止匹配下一个索引键;若是不存在,直接中止下边界匹配。
exp: idx_c1_c2_c3(c1,c2,c3) where c1>=1 and c2>2 and c3=1 –> first key (c1,c2) –> c1为 ‘>=’ ,加入下边界界定,继续匹配下一个 –> c2 为 ‘>’,加入下边界界定,中止匹配
上边界(last key)和下边界(first key)相似,首先判断是不是否是(=,<=)中的一种,若是是,加入界定,继续下一个索引键值匹配,若是是(<),加入界定,中止匹配。
exp: idx_c1_c2_c3(c1,c2,c3) where c1<=1 and c2=2 and c3<3 –> first key (c1,c2,c3) –> c1为 ‘<=’,加入上边界界定,继续匹配下一个 –> c2为 ‘=’加入上边界界定,继续匹配下一个 –> c3 为 ‘<‘,加入上边界界定,中止匹配
注:这里简单的记忆是,若是比较符号中包含’=’号,’>=’也是包含’=’,那么该索引键是能够被利用的,能够继续匹配后面的索引键值;若是不存在’=’,也就是’>’,'<‘,这两个,后面的索引键值就没法匹配了。同时,上下边界是不能够混用的,哪一个边界能利用索引的的键值多,就是最终可以利用索引键值的个数。
字面理解就是能够用索引去过滤。也就是字段在索引键值中,可是没法用去肯定Index Key的部分。
exp: idex_c1_c2_c3 where c1>=1 and c2<=2 and c3 =1 index key –> c1 index filter–> c2 c3
这里为何index filter 只是c1呢?由于c2 是用来肯定上边界的,可是上边界的c1没有出现(<=,=),而下边界中,c1是>=,c2没有出现,所以index key 只有c1字段。c2,c3 都出如今索引中,被当作index filter。
没法利用索引完成过滤,就只能用table filter。此时引擎层会将行数据返回到server层,而后server层进行table filter。
那么若是查询中存在between 和like,MySQL是如何进行处理的呢?
where c1 between 'a' and 'b'
等价于where c1>='a' and c1 <='b'
,因此进行相应的替换,而后带入上层模型,肯定上下边界便可。
首先须要确认的是%不能是最在最左侧,where c1 like '%a'
这样的查询是没法利用索引的,由于索引的匹配须要符合最左前缀原则。
where c1 like 'a%'
其实等价于where c1>='a' and c1<'b'
你们能够仔细思考下。
在数据库中,若是没法利用索引完成排序,随着过滤数据的数据量的上升,排序的成本会愈来愈大,即便是采用了limit,可是数据库是会选择将结果集进行所有排序,再取排序后的limit 记录,并且MySQL 针对能够用索引完成排序的limit 有优化,更能减小成本。
Make sure it uses index It is very important to have ORDER BY with LIMIT executed without scanning and sorting full result set, so it is important for it to use index – in this case index range scan will be started and query execution stopped as soon as soon as required amount of rows generated.<
pre class=””>CREATE TABLE
t1
(
id
int(11)NOT NULL AUTO_INCREMENT,
c1
int(11)NOT NULL DEFAULT‘0’,
c2
int(11)NOT NULL DEFAULT‘0’,
c3
int(11)NOT NULL DEFAULT‘0’,
c4
int(11)NOT NULL DEFAULT‘0’,
c5
int(11)NOT NULL DEFAULT‘0’,
PRIMARY KEY(id
),
KEYidx_c1_c2_c3
(c1
,c2
,c3
))ENGINE=InnoDBAUTO_INCREMENT=8DEFAULT CHARSET=utf8mb4select*fromt1;
+—-+—-+—-+—-+—-+—-+
|id|c1|c2|c3|c4|c5|
+—-+—-+—-+—-+—-+—-+
|1|3|3|2|0|0|
|2|2|4|5|0|0|
|3|3|2|4|0|0|
|4|1|3|2|0|0|
|5|1|3|3|0|0|
|6|2|3|5|0|0|
|7|3|2|6|0|0|
+—-+—-+—-+—-+—-+—-+
7rowsinset(0.00sec)
selectc1,c2,c3fromt1;
+—-+—-+—-+
|c1|c2|c3|
+—-+—-+—-+
|1|3|2|
|1|3|3|
|2|3|5|
|2|4|5|
|3|2|4|
|3|2|6|
|3|3|2|
+—-+—-+—-+
7rowsinset(0.00sec)
存在一张表,c1,c2,c3上面有索引,select c1,c2,c3 from t1
;
查询走的是索引全扫描,所以呈现的数据至关于在没有索引的状况下select c1,c2,c3 from t1 order by c1,c2
****,c3
`;`的结果。 所以,索引的有序性规则是怎么样的呢?
c1=3 —> c2 有序,c3 无序__c1=3,c2=2 — > c3 有序__c1 in(1,2) —> c2 无序 ,c3 无序
有个小规律,idx_c1_c2_c3,那么如何肯定某个字段是有序的呢?c1 在索引的最前面,确定是有序的,c2在第二个位置,只有在c1 惟一肯定一个值的时候,c2才是有序的,若是c1有多个值,那么c2 将不必定有序,同理,c3也是相似
针对MySQL索引,我这边只是提到了在单表查询状况下的模型,经过这篇文章,想必你们应该了解到MySQL大部分状况下是如何利用索引的,若是存在疑问,欢迎联系我😯
做者:王航威 – fordba.com
来源:http://fordba.com/spend-10-mi...