我们经常会遇到两种情况:

  • 明明在某个字段上加了索引,但实际上并没有生效。
  • 索引有时候生效了,有时候没有生效。

索引失效的场景汇总如下:

  1. 使用select *
  2. 索引列上有计算操作
  3. 索引列上有函数操作
  4. 字段类型不同
  5. like左边包含%
  6. 进行索引的列对比
  7. not innot exist

准备数据

CREATE TABLE example
(  id      int NOT NULL AUTO_INCREMENT,  code    varchar(20) DEFAULT NULL,  age     int         DEFAULT 0,  name    varchar(30) DEFAULT NULL,  height  int         DEFAULT 0,  PRIMARY KEY (id),  KEY idx_code_age_name (code, age, name),  KEY idx_height (height)
); INSERT INTO example (id, code, age, name, height, address)
VALUES (1, '10', 21, '张三', 175, '北京');
INSERT INTO example(id, code, age, name, height, address)
VALUES (2, '11', 18, '李四', 173, '上海');
INSERT INTO example (id, code, age, name, height, address)
VALUES (3, '12', 23, '王武', 174, '广州');
INSERT INTO example (id, code, age, name, height, address)
VALUES (4, '13', 22, '马六', 154, '重庆');

创建了三个索引

  • id:数据库的主键
  • idx_code_age_name:由code、age和name三个字段组成的联合索引
  • idx_height:普通索引

查看执行计划,可以使用explain关键字,例如:

explain select * from example where id=1;

执行结果:

从图中可以看出,由于id字段是主键,该SQL语句用到了主键索引

使用select *

案例SQL

explain
select * from example where name='苏三';

执行结果

说明

在该SQL中用了select *,从执行结果看,走了全表扫描,没有用到任何索引,查询效率是非常低的。
如果查询的时候,只查我们真正需要的列,而不查所有列,查询效率会有提升

explain
select code,name from example
where name='苏三';

执行结果

从执行结果不难看出,该SQL语句这次走了全索引扫描,比全表扫描效率更高

如果select语句中的查询列,都是索引列,那么这些列被称为覆盖索引。这种情况下,查询的相关字段都能走索引,索引查询效率相对来说更高一些,而使用select *查询所有列的数据,大概率会查询非索引列的数据,非索引列不会走索引,查询效率非常低

索引列上有计算操作

顾名思义就是在查询条件上加上计算比对操作,如下面的例子,id列上有计算:

explain select * from example where id+1=2;

执行结果:

从上图中的执行结果,能够非常清楚的看出,该id字段的主键索引,在有计算的情况下失效了

索引列上有函数操作

有时候我们在某条SQL语句的查询条件中,需要使用函数,比如:截取某个字段的长度
例如想要查询身高带有17开头的用户

explain select * from example where SUBSTR(height,1,2)=17;

执行结果

在使用该函数之后,该SQL语句走了全表扫描,索引失效

此处讨论的是函数操作对索引的影响,因此like关键字不再此讨论范围内

字段类型不同

在SQL语句中因为字段类型不同,而导致索引失效的问题,很容易遇到,可能是我们日常工作中最容易忽略的问题
在sql语句中查询数据时,查询条件我们可以写成这样:

explain
select * from example where code='101';

执行结果:

从上图中看到,该code字段走了索引,但如果在写SQL时,不小心把引号弄掉了,把SQL语句变成了

explain
select * from example where code=101;

执行结果:

你会惊奇的发现,该SQL语句竟然变成了全表扫描。因为少写了引号,这种小小的失误,竟然让code字段上的索引失效了
因为code字段的类型是varchar,而传参的类型是int,两种类型不同,导致了索引失效
但是有时大家也会发现下面一种场景:

explain
select * from example where height='175';

执行结果:

从图中看出该SQL语句确实走了索引。int类型的参数,不管在查询时加没加引号,都能走索引,这是因为MySQL发现如果是int类型字段作为查询条件时,它会自动将该字段的传参进行隐式转换,把字符串转换成int类型。

因此在写SQL时,需要确保查询条件的类型与查询字段类型一致,以免发生不必要的转换,消耗数据库的性能。

like左边包含

模糊查询,在我们日常的工作中,使用频率还是比较高的
目前like查询主要有三种情况:

  • like ‘a%’
  • like ‘%a’
  • like ‘%a%’

例如:想查出所有code是10开头的用户

explain
select * from example where code like '10%';

执行结果:

图中看出这种%在10右边时走了索引

例如:如果想查出所有code是1结尾的用户

explain
select * from example where code like '%1';

执行结果:

从图中看出这种%在1左边时,code字段上索引失效了,该SQL变成了全表扫描

此外,如果出现以下SQL

explain
select * from example where code like '%1%';

执行结果:

该SQL语句的索引也会失效
因为索引就像字典中的目录,一般目录是按字母或者拼音从小到大,从左到右排序,是有顺序的。 我们在查目录时,通常会先从左边第一个字母进行匹对,如果相同,再匹对左边第二个字母,如果再相同匹对其他的字母,以此类推。通过这种方式我们能快速锁定一个具体的目录,或者缩小目录的范围

进行索引的列对比

过滤出表中某两列值相同的记录。比如example表中id字段和height字段,查询出这两个字段中值相同的记录

explain
select * from example where id=height;

执行结果:

从图中可以看出,索引失效了。
id字段本身是有主键索引的,同时height字段也建了普通索引的,并且两个字段都是int类型,类型是一样的。
但如果把两个单独建了索引的列,用来做列对比时索引会失效

not innot exist

在我们日常工作中用得也比较多的,还有范围查询,常见的有:

  • in
  • exists
  • not in
  • not exists
  • between and

not in

假如我们想查出height不在某些范围之内的用户,这时SQL语句可以这样写:

explain
select * from example where height not in (173,174);

执行结果:

从上图可以看出,索引在此处失效了

not exists

SQL在使用not exists也会出现索引失效的情况,具体SQL如下:

explain
select * from example  t1
where  not exists (select 1 from example t2 where t2.height=173 and t1.id=t2.id);

执行结果:

从图中看出SQL语句中使用not exists关键后,t1表走了全表扫描,并没有走索引

如有疑问请提issue: https://gitee.com/huangmike/itshare

Mysql索引失效场景集合相关推荐

  1. 15个必知的Mysql索引失效场景,别再踩坑了

    背景 无论你是技术大佬,还是刚入行的小白,时不时都会踩到Mysql数据库不走索引的坑.常见的现象就是:明明在字段上添加了索引,但却并未生效. 前些天就遇到一个稍微特殊的场景,同一条SQL语句,在某些参 ...

  2. mysql 数据倾斜 索引_索引,索引优化,mysql索引失效场景

    索引 保证数据完整性. 关注索引的两个点:树和有序(树可以定位索引的起点,有序可以定位索引的终点) 1.每个表都是一个索引组织表(集群表) 以主键来组织的一个表 主键索引 2.其他索引都是二级索引 每 ...

  3. MYSQL索引失效场景

    1:索引字段使用了计算或者函数 2:索引字段数据类型不一致 比如索引字段是数字类型却传入了字符串类型 3:违反了最左匹配原则 使用(> < like between 等范围查询索引会无效 ...

  4. MySQL 索引失效的 15 种场景!

    背景 无论你是技术大佬,还是刚入行的小白,时不时都会踩到Mysql数据库不走索引的坑.常见的现象就是:明明在字段上添加了索引,但却并未生效. 前些天就遇到一个稍微特殊的场景,同一条SQL语句,在某些参 ...

  5. MySQL索引失效的几种常见场景

    前言 我们在使用MySQL查询数据的时候,总会遇见没有正确使用到索引的情况. 这里我们列举几种常见的,搜索条件使用了索引列却没有走索引的场景. (以下测试均在MySQL8.0.28中完成,且所有数据均 ...

  6. MySQL 索引失效详解

    MySQL 索引失效详解 一.MySQL索引失效原因汇总 隐式的类型转换,索引失效 查询条件包含or,可能导致索引失效 like通配符可能导致索引失效 查询条件不满足联合索引的最左匹配原则 在索引列上 ...

  7. mysql 索引失效分析

    大神总结的索引失效一句话理解后就不用看我下面的文章了,这就是 "模型数空运最快" 模:模糊查询like  %在前面索引失效 型:数据类型有变化索引失效 数:索引列使用了函数索引失效 ...

  8. 什么情况会导致 MySQL 索引失效?

    为了验证 MySQL 中哪些情况下会导致索引失效,我们可以借助 explain 执行计划来分析索引失效的具体场景. explain 使用如下,只需要在查询的 SQL 前面添加上 explain 关键字 ...

  9. like左匹配索引失效_导致MySQL索引失效的一些常见写法总结

    前言 最近一直忙着处理原来老项目遗留的一些SQL优化问题,由于当初表的设计以及字段设计的问题,随着业务的增长,出现了大量的慢SQL,导致MySQL的CPU资源飙升,基于此,给大家简单分享下这些比较使用 ...

最新文章

  1. python绘制简单图形-python绘制数学图形(堪比matlab)
  2. 29、剑指offer--最小的K个数
  3. 设计模式学习笔记(总结篇:模式分类)
  4. pythontxt文件怎么读_python怎么读txt文件
  5. 类成员初始化顺序php,PHP-php类成员变量初始化的问题?
  6. vim与Python推荐之插件Autopep8
  7. proxool配置多数据库多连接池
  8. 程序员最讨厌的9句话
  9. Python学习笔记九:文件I/O
  10. 用 Graphviz+pvtrace 可视化函数调用
  11. CentOS 7 + Win 双系统的安装遇到的重要问题
  12. 下载XAMPP并安装和使用(Mac环境)
  13. 你焊接过最小的贴片器件是多大?
  14. GNU C Complier - GNU Compiler Collection - GCC
  15. UOJ#449. 【集训队作业2018】喂鸽子(期望dp)
  16. 参加计算机培训典型材料,计算机应用专业典型学员事迹材料
  17. Google 推出浏览器版Google Voice
  18. 使用BDC进行Miro录屏时的公司代码弹窗问题
  19. vue-router.esm-bundler.js?6c02:1474 Uncaught TypeError: Cannot read property ‘forEach‘ of undefined
  20. Arduino基础篇(七)-- 如何使用DS18B20数字温度传感器(基于OneWire和DallasTemperature库)

热门文章

  1. iOS开发-Interface Builder的前世今生
  2. linux系统有哪些电脑,低配电脑装linux系统好吗,或者有什么别的系统推荐吗?...
  3. Git冲突解决之P4Merge
  4. 微信小程序——editor显示html和生成html、用parser显示html文本
  5. 豆瓣评分小程序Part-1
  6. 安卓手机当做电脑摄像头使用,Android 8.0 + Win10亲测可用
  7. 学了三年的PS 全部在这里了,都是精华(photoshop常用操作)
  8. Unity3d 性能优化篇
  9. 电商产品设计:后台营销功能模块设计-砍价活动(二)
  10. NAT SIP helper