引起索引失效的原因

索引失效情况

1.最左匹配法则

复合索引a-b-c,where条件中 :

a用到,

a and b用到,

b and a用到,

a and c用到,

c and a用到,

a and b and c用到,

c and b and a用到,

b用不到,

c用不到,

b and c用不到,

c and b用不到,

a or b用不到,

b or c用不到,

a or b or c用不到,

(a or b) and c用不到,

(a and b) or c用不到,

(a or d) and b and c 用不到
单列索引a,单列索引b,单列索引c,where条件中 :

a or b 均用不到,

a or b or c 均用不到,

a and b 用到 a的索引,

a and b and c 用到a的索引,

c and b 用到b的索引(谁的索引定义在前面用谁的),

(a and b ) or c 均用不到,

(a or b ) and c 用到c的索引
————————————————
版权声明:本文为CSDN博主「二十六画生的博客」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u010002184/article/details/89388600
索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。

2.OR 前后只要存在非索引的列,都会导致索引失效

3.like以通配符%开头索引失效

用不到:like '%abc' 或者 like '%abc%'
用到: like 'abc%'

4.范围条件右边的列索引失效

a用到(比如a> xxx 或者 a>=yyy 或者 a >xxx and a  xxx or a 
step1:
#创建一个联合索引, 注意字段的顺序
create index idx_age_classid_name on student(age,classid,name);
#执行计划
EXPLAIN SELECT SQL_NO_CACHE * FROM student
WHERE student .age = 30 AND student .classId > 20 AND student .name = 'abc' ;  

step2:
#再创建一个联合索引,与上面的索引对比字段顺序变了
create index idx_age_name_classid on student(age,name,classid); 
#再执行一模一样的执行计划
EXPLAIN SELECT SQL_NO_CACHE * FROM student
WHERE student .age = 30 AND student .classId > 20 AND student .name = 'abc' ;

第一个没用全,只用到了联合索引“idx_age_classid_name” 的age和classid。
第二个把联合索引“idx_age_name_classid”的age,name和classid都用上了。

5.计算、函数、类型转换(自动或手动)导致索引失效

select * from user where name = 120
select * from user where name = '120'
mysql 在第一条语句中将检测值为int 进行类型转换查询,导致索引失效

6.is null可以使用索引,is not null无法使用索引

7.不等于(!= 或者<>)导致索引失效

8.数据库和表的字符集统一使用utf8mb4

统一使用utf8mb4( 5.5.3 版本以上支持 ) 兼容性更好,统一字符集可以避免由于字符集转换产生的乱码。
不同的 字符集 进行比较前需要进行 转换 会造成索引失效。

9.主键插入顺序

可这个数据页已经满了,再插进来咋办呢?我们需要把当前 页面分裂 成两个页面,把本页中的一些记录移动到新创建的这个页中。
页面分裂和记录移位意味着什么?
意味着: 性能损耗 !所以如果我们想尽量 避免这样无谓的性能损耗,最好让插入的记录的 主键值依次递增 ,这样就不会发生这样的性能损耗了。
所以我们建议:让主键具有 AUTO_INCREMENT ,让存储引擎自己为表生成主键,
在插入记录时存储引擎会自动为我们填入自增的主键值。这样的主键占用空间小,顺序写入,减少页分裂。
————————————————

原文链接:https://blog.csdn.net/qq_63815371/article/details/124337932

10.In not In

当in的取值范围较小时,in会走索引;
当in的取值范围较大时,in不走索引,而是会用全表扫描。因为in的条件过多时,返回的数据就会很多,可能会导致应用堆内内存溢出,导致索引失效。
not in ,单列索引a ,where a not in (xxxxx) ,不管里面是一个还是多个参数都用不到a的索引(包括int和varchar类型的字段)

不必要使用索引情况

1.唯一性差

当字段为性别时,意味着二叉树的级别少,多是平级,检索数据量大

2.频繁更新的字段(更新消耗)

3.where中不用的字段

你可能感兴趣的:(引起索引失效的原因)