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,查询结果如下:
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';
三个sql均用到了索引,并且第三个的key_len最精确,这是我们在工作中追求的。
2. 最佳左前缀法则
索引均没起到作用,进行的全表扫描。
而如果使用name和psot,位置1和3列:
explain SELECT * FROM staffs where name = 'july';
explain SELECT * FROM staffs where name = 'july' and pos = 'dex';
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';
在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';
如果中间的age 使用了范围检索:
explain SELECT * FROM staffs where name = 'july' and age > 23 and pos = 'dex';
口诀:范围之后全失效
比如in、between and、>、<这些之后的索引字段都失效。
5.尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select*
6.mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描
7.is null,is not null 也无法使用索引
8.like以通配符开头('$abc...')mysql索引失效会变成全表扫描操作
问题:解决like'%字符串%'索引不被使用的方法??
但是这地方,likex写法不一样,分析结果一致,无区别。这里要和5.x版本区别开
9.字符串不加单引号索引失效
字符串必须加单引号或者双引号;数字类型会隐式转换倒置索引失效。
10.少用or,用它连接时会索引失效
在这里,or条件下,type为index,5.7下则为ALL,要区别开来。