MySQL高级知识(六)——索引优化

前言:索引优化的目的主要是让索引不失效,本篇经过相关案例对索引优化进行讲解。html


0.准备

建立经典的tb_emp表。sql

DROP TABLE IF EXISTS `tb_emp`;
CREATE TABLE `tb_emp` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `age` int(11) NOT NULL,
  gender varchar(10) NOT NULL,
email varchar(20),
PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- ---------------------------- INSERT INTO `tb_emp` (name,age,gender,email) VALUES ('Tom', '22','male','1@qq.com'); INSERT INTO `tb_emp` (name,age,gender,email) VALUES ('Mary', '21','female','2@qq.com'); INSERT INTO `tb_emp` (name,age,gender,email) VALUES ('Jack', '27','male','3@qq.com'); INSERT INTO `tb_emp` (name,age,gender,email) VALUES ('Rose', '23','female','4@qq.com');

注:建立了tb_emp表,并插入了4条数据。函数

1.最佳左前缀法则

#1.定义:在建立了多列索引的状况下,查询从索引的最左前列开始且不能跳过索引中的列优化

最佳左前缀法则就是说若是建立了多个索引,在使用索引时要按照建立索引的顺序来使用,不能缺乏或跳过,固然若是只使用最左边的索引列,也就是第一个索引是能够的,通俗理解:“带头大哥不能死,中间兄弟不能断”。要点:“头不能掉”。下面将用案例进行说明。spa

#2.建立组合索引,并执行explain。3d

Case 1:code

分析:htm

①索引的建立顺序为name,age,gender;blog

②直接使用name(带头大哥)做为条件,能够看到type=ref,key_len=82,ref=const,效果还不错。索引

Case 2:

分析:

没使用带头大哥(name),直接用兄弟,type=ALL,为全表扫描。

Case 3:

分析:

①对比上面两句sql语句可发现:咱们使用:火车头(name)和中间车箱(age)、火车头(name)和车尾(gender)

②虽然type=ref,可是观察key_len和ref两项,并对比Case1中的结果,可得出在使用火车头(name)和车尾(gender)时,只使用了部分索引也就是火车头(name)的索引。

③通俗理解:火车头单独跑没问题,火车头与直接相连的车箱一块儿跑也没问题,可是火车头与车尾,若是中间没有车箱,只能火车头本身跑。

Case 4:

分析:

火车头加车箱加车尾,三者串联,就变成了奔跑的小火车。type=ref,key_len=128,ref=const,const,const。

最佳左前缀法则总结:带头大哥不能死,中间兄弟不能断;带头大哥可跑路,老二也可跟着跑,其他兄弟只能死

2.不要在索引列上作任何操做

在索引列上作任何操做(计算、函数、(自动or手动)类型转换),会致使索引失效从而转向全表扫描。

Case 1:

分析:

这里使用了函数计算,type=ALL,致使索引失效。

Case 2:

分析:

将name=‘Tom’的值修改成‘123’,使用sql后,发生了类型转换,type=ALL,致使全表扫描。

结论:在索引列上作任何操做,都会致使索引失效转向全表扫描

3.范围右边全失效

存储引擎不能使用索引中范围右边的列,也就是说范围右边的索引列会失效

Case 1:

Case 2:

Case 3:

Case 4:

对以上4个case进行分析:

①条件单独使用name时,type=ref,key_len=82,ref=const。

②条件加上age时(使用常量等值),type=ref,key_len=86,ref=const,const。

③当全值匹配时,type=ref,key_len=128,ref=const,const,const。说明索引所有用上,从key_len与ref能够看出。

④当使用范围时(age>27),type=range,key_len=86,ref=Null,与Case 一、Case2和Case3可知,使用了部分索引,但gender索引没用上(与Case 3对比)。

结论:范围右边的索引列失效

4.尽可能使用覆盖索引

尽可能使用覆盖索引(查询列和索引列尽可能一致,通俗说就是对A、B列建立了索引,而后查询中也使用A、B列),减小select *的使用。

Case 1:

Case 2:

分析:

对比Case1和Case2,Case1使用select *,Case2使用覆盖索引(查询列与条件列对应),可看到Extra从Null变成了Using index,提升检索效率。

5.使用不等于(!=或<>)会使索引失效

结论:使用!=会使type=ALL,key=Null,致使全表扫描,而且索引失效

6.is null 或 is not null也没法使用索引

Case 1:

Case 2:

分析:

在使用is null的时候,索引彻底失效,使用is not null的时候,type=ALL全表扫描,key=Null索引失效。

这里的例子可能有点特殊,具体状况肯能和case上的有所不一样,可是仍是要注意is null和is not null的使用。

7.like通配符以%开头会使索引失效

Case 1:

Case 2:

Case 3:

分析:

like的%位置不一样,所产生的效果不同,当%出如今左边的时候type=ALL,key=Null(全表扫描,索引失效),当%出如今右边的时候,type=range,索引未失效。

like查询为范围查询,%出如今左边,则索引失效。%出如今右边索引未失效。口诀:like百分加右边。

可是在实际生产环境中,%仅出如今右边可能不可以解决咱们的问题,因此解决%出如今左边索引失效的方法:使用覆盖索引

Case 4:

分析:对比Case1可知,经过覆盖索引type=index,而且使用了Using index,从全表扫描变成了全索引扫描,仍是不错的。

Case 5:

分析:这里出现type=index,由于主键自动建立惟一索引

Case 6:

分析:上面四组explain执行的结果都相同,代表都使用了索引,从这里能够深入的体会到覆盖索引:彻底吻合或者沾边(age),均可以使type=index。

Case 7:

分析:因为只在(name,age,gender)上建立索引,当包含email时,致使结果集偏大(email未建索引)【锅大,锅盖小,不能匹配】,因此type=ALL。

8.字符串不加单引号致使索引失效

Case 1:

分析:上述两条sql语句都能查询出相同的数据。

Case 2:

分析:

经过explain执行结果能够看出,字符串(name)不加单引号在查询的时候,致使索引失效(type=ref变成了type=ALL,而且key=Null),并全表扫描。

结论:varchar类型的字段,在查询的时候不加单引号致使索引失效,转向全表扫描

9.少用or,用or链接会使索引失效

结论:经过上述explain的执行结果可看出,在使用or链接的时候type=ALL,key=Null,索引失效,并全表扫描

总结

①全值匹配。

②最佳左前缀法则:带头大哥不能死,中间兄弟不能断;带头大哥可跑路,老二也可跟着跑,其他兄弟只能死

索引列上不计算

覆盖索引记住用

不等于、is null、is not null致使索引失效

like百分加右边,加左边致使索引失效解决方法:使用覆盖索引。

字符串不加单引号致使索引失效

少用or,用or致使索引失效


by Shawn Chen,2018.6.25日,上午。


相关内容

MySQL高级知识系列目录

相关文章
相关标签/搜索