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,要区别开来。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.explain 有时在使用explain时,感觉有些条件一定能使用到索引,但是并没有使用到,可能是数据少,my...
    sizuoyi00阅读 878评论 0 0
  • 一、索引设计原则 在MySQL中常用的B+树索引分为聚簇索引和辅助索引,关于辅助索引,虽然个数没有限制(聚簇索引一...
    张伟科阅读 817评论 0 2
  • 索引是什么可以理解为排好序的方便快速查找的一种数据结构,索引有很多种,这里介绍BTree类型的索引。索引虽然可以提...
    AD甜蜜蜜阅读 1,781评论 2 5
  • 说到索引,很多人都知道“索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址,在数据...
    爱情小傻蛋阅读 703评论 2 2
  • 我第一次玩旱冰鞋,旱冰鞋长着四个轮子。那轮子转起来像风火轮一样快,我穿上旱冰鞋东倒西歪,根本站不起来。在姐姐的帮助...
    杨皓轩阅读 106评论 0 0