mysql-索引优化原则

mysql-version:8.0.19

DROP TABLE IF EXISTS `staffs`;
CREATE TABLE `staffs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(24) NOT NULL,
  `age` int(11) NOT NULL DEFAULT '0',
  `pos` varchar(20) NOT NULL,
  `add_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
insert into staffs(name,age,pos,add_time) values ('z3',22,'manager',NOW());
insert into staffs(name,age,pos,add_time) values ('july',23,'dex',NOW());
insert into staffs(name,age,pos,add_time) values ('2000',23,'manager',NOW());
 
alter table staffs add index idx_staffs_nap(name,age,pos);
SELECT * FROM staffs where name = 'july';

,此时已经建立联合索引,name,age,pos,查询结果如下:


image.png
1.全值匹配我最爱
explain SELECT * FROM staffs where  name = 'july';
explain SELECT * FROM staffs where  name = 'july' and age = 23;
explain SELECT * FROM staffs where name = 'july' and age = 23 and pos = 'dex';
image.png

三个sql均用到了索引,并且第三个的key_len最精确,这是我们在工作中追求的。

2. 最佳左前缀法则
image.png

索引均没起到作用,进行的全表扫描。
而如果使用name和psot,位置1和3列:

explain SELECT * FROM staffs where name = 'july';
explain SELECT * FROM staffs where name = 'july'  and pos = 'dex';
比对.png

ref中const只有一个,key_len只有74,和单name检索一致,故此只有name索引生效,pos无效。中间的索引字段没用,那么就相当于只用了一部分索引,第一字段进行索引。
由此得到,最佳左前缀法则:

1. 口诀1:带头大哥不能死(最左前列开始)。
2. 口诀2:中间兄弟不能断(不跳过索引中的列)。

3. 不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
#1
1.SELECT * FROM staffs where name = 'july';
#2
explain SELECT * FROM staffs where name = 'july';
#3
explain SELECT * FROM staffs where left(name,4) = 'july';
image.png

在name上使用了left函数,则使原索引失效。

4.存储引擎不能使用索引中范围条件右边的列
#分析1
explain SELECT * FROM staffs where name = 'july';
#分析2
explain SELECT * FROM staffs where name = 'july' and age = 23;
#分析3
explain SELECT * FROM staffs where name = 'july' and age = 23 and pos = 'dex';
image.png

如果中间的age 使用了范围检索:

explain SELECT * FROM staffs where name = 'july' and age > 23 and pos = 'dex';
name 和age被使用.png

口诀:范围之后全失效
比如in、between and、>、<这些之后的索引字段都失效。

5.尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select*
比对.png

6.mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描

比对.png

7.is null,is not null 也无法使用索引

比对.png

8.like以通配符开头('$abc...')mysql索引失效会变成全表扫描操作
问题:解决like'%字符串%'索引不被使用的方法??

mysql5.7下比对.png
mysql8.0.19下比对.png

但是这地方,likex写法不一样,分析结果一致,无区别。这里要和5.x版本区别开

9.字符串不加单引号索引失效
image.png

字符串必须加单引号或者双引号;数字类型会隐式转换倒置索引失效。

10.少用or,用它连接时会索引失效
5.7下or.png
8.0.19下or.png

在这里,or条件下,type为index,5.7下则为ALL,要区别开来。

你可能感兴趣的:(mysql-索引优化原则)