mysql 整型 引号 索引_MySQL常见索引失效

MySQL常见索引失效

索引失效的原因有很多种, 这里列举一些常见失效案例。

首先创建表和数据

create table staffs(

id int primary key auto_increment,

name varchar(24) not null default '' comment '姓名',

age int not null default 0 comment '年龄',

pos varchar(20) not null default '' comment '职位',

add_time timestamp not null default current_timestamp comment '入职时间'

) charset utf8 comment '员工登记表';

insert into staffs(name,age,pos,add_time)values('z3',22,'manager',now());

insert into staffs(name,age,pos,add_time)values('July',23,'dev',now());

insert into staffs(name,age,pos,add_time)values('tom',23,'dev',now());

...

添加索引:

# 添加复合索引 name,age,pos

alter table staffs add index idx_staffs_nameAgePos(name,age,pos);

1.单个--多个索引匹配

0640d9f5ee1b5dacfd18115174d98ec9.png

4026309e528d194eb064baf4fb10d4fe.png

3f7ba5617304484155e6ce30fb9134aa.png

伴随where后面查询精度越大,key_len越大,ref中const越多,代价也会越大。

2.未遵循最左前缀原则

852f6af59ff29e14981762ba3c62c974.png

建立索引顺序是name,age,pos,直接查询age,未遵循最左前缀中开头必为建立索引的字段。从而导致索引失效。

8712c80d7499a31965bc6aab34bedb7e.png

上面只引用了部分索引,从key_len可以看出,并且ref就一个常量,违背了最左前缀的中间部分不能省,导致只右部分索引起效

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

所说的操作指的是计算,函数,自动或手动的类型转换,这样会导致索引失效,从而转换全表扫描

96b7e3851722d02b9a54ef2b93495714.png

使用left函数,导致索引失效

4.范围检索也会让索引失效

87803faa79b170806e08743f7fadd70c.png

因为第二个字段使用范围查找,导致第二个索引用途不是检索而是排序,这样导致第三个索引失效。

常用范围查找有:in/like/between/>

5.尽量使用覆盖索引

6fd7660a507c7674806ee48f1d1b21f8.png

1和2执行计划对比,可以看第二个Extra使用Using where,Using index,这样表示用索引检索并查询。

而3,4对比可以看出虽然第三个执行计划的第二个索引字段使用age>25的范围排序,最起码第一个索引是生效的。

这都是得益于select 索引字段,而不是select *

6.使用不等于(!= or <>) 无法使用索引

使用不等于导致全表扫描

1f11a64b1ad26662efb7172068fb5ebc.png

可以看到type=ALL为全表扫描

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

c8b6455f4c31b48f001a98472a79a926.png

为了避免此类事情发生最好设置default值

8. like 以通配符开头"%abc" 会造成全表扫描

4d952ceda8693a6270178b7934065963.png

而通过常量开头不会导致索引失效

06d6321d2ca86c8b1aee09786b65584b.png

当然如果你执意像要通配符形式为%abc%形式让索引不失效也是可以的:

创建表和数据,示例:

create table `tbl_user`(

`id` int(10) not null auto_increment,

`name` varchar(20) default null,

`age` int(11) default null,

`email` varchar(20) default null,

primary key(`id`)

)engine=innodb auto_increment=1 default charset=utf8;

insert into tbl_user(name,age,email)values('1aa1',21,'aaa@163.com');

insert into tbl_user(name,age,email)values('2aa2',22222,'bbb@163.com');

insert into tbl_user(name,age,email)values('3aa3',33333,'ccc@163.com');

创建覆盖索引:

create index idx_user_nameAge on tbl_user(name,age);

我们可以看到给name,age创建覆盖索引

fa7ce2e91a0a6e8c27743cf112282d21.png

ce58ecab7c3b236f028bd8b7760f3e45.png

我们指定查询的字段使用覆盖索引全,单字段,都不会造成索引失效

c29f2867445363334b25edb6d6090e4f.png

但我们添加email(email不是我们创建索引字段),就会造成全表扫描,email就好像搅屎棍一样,导致索引失效

所以通过:select [覆盖索引or 主键索引 or 覆盖索引沾边的字段] from staffs where name like '%July%';可以不会让索引失效,通常type为index

9.字段不是整形不加单引号

字符串不加单引号索引失效 name为varchar类型 ,必须使用单引号。 否则会失效。

0dd56c96d67ff8c25f905d949796cf12.png

name字段类型为varchar,但是我们查询条件为整型,其内部SQL会自行将int类型转换字符串,但是索引失效

10.少用or

用它连接也会导致索引失效。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值