Mysql索引失效场景集合
我们经常会遇到两种情况:
- 明明在某个字段上加了索引,但实际上并没有生效。
- 索引有时候生效了,有时候没有生效。
索引失效的场景汇总如下:
- 使用
select *
- 索引列上有计算操作
- 索引列上有函数操作
- 字段类型不同
- like左边包含
%
- 进行索引的列对比
not in
和not 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 in
和not 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索引失效场景集合相关推荐
- 15个必知的Mysql索引失效场景,别再踩坑了
背景 无论你是技术大佬,还是刚入行的小白,时不时都会踩到Mysql数据库不走索引的坑.常见的现象就是:明明在字段上添加了索引,但却并未生效. 前些天就遇到一个稍微特殊的场景,同一条SQL语句,在某些参 ...
- mysql 数据倾斜 索引_索引,索引优化,mysql索引失效场景
索引 保证数据完整性. 关注索引的两个点:树和有序(树可以定位索引的起点,有序可以定位索引的终点) 1.每个表都是一个索引组织表(集群表) 以主键来组织的一个表 主键索引 2.其他索引都是二级索引 每 ...
- MYSQL索引失效场景
1:索引字段使用了计算或者函数 2:索引字段数据类型不一致 比如索引字段是数字类型却传入了字符串类型 3:违反了最左匹配原则 使用(> < like between 等范围查询索引会无效 ...
- MySQL 索引失效的 15 种场景!
背景 无论你是技术大佬,还是刚入行的小白,时不时都会踩到Mysql数据库不走索引的坑.常见的现象就是:明明在字段上添加了索引,但却并未生效. 前些天就遇到一个稍微特殊的场景,同一条SQL语句,在某些参 ...
- MySQL索引失效的几种常见场景
前言 我们在使用MySQL查询数据的时候,总会遇见没有正确使用到索引的情况. 这里我们列举几种常见的,搜索条件使用了索引列却没有走索引的场景. (以下测试均在MySQL8.0.28中完成,且所有数据均 ...
- MySQL 索引失效详解
MySQL 索引失效详解 一.MySQL索引失效原因汇总 隐式的类型转换,索引失效 查询条件包含or,可能导致索引失效 like通配符可能导致索引失效 查询条件不满足联合索引的最左匹配原则 在索引列上 ...
- mysql 索引失效分析
大神总结的索引失效一句话理解后就不用看我下面的文章了,这就是 "模型数空运最快" 模:模糊查询like %在前面索引失效 型:数据类型有变化索引失效 数:索引列使用了函数索引失效 ...
- 什么情况会导致 MySQL 索引失效?
为了验证 MySQL 中哪些情况下会导致索引失效,我们可以借助 explain 执行计划来分析索引失效的具体场景. explain 使用如下,只需要在查询的 SQL 前面添加上 explain 关键字 ...
- like左匹配索引失效_导致MySQL索引失效的一些常见写法总结
前言 最近一直忙着处理原来老项目遗留的一些SQL优化问题,由于当初表的设计以及字段设计的问题,随着业务的增长,出现了大量的慢SQL,导致MySQL的CPU资源飙升,基于此,给大家简单分享下这些比较使用 ...
最新文章
- python绘制简单图形-python绘制数学图形(堪比matlab)
- 29、剑指offer--最小的K个数
- 设计模式学习笔记(总结篇:模式分类)
- pythontxt文件怎么读_python怎么读txt文件
- 类成员初始化顺序php,PHP-php类成员变量初始化的问题?
- vim与Python推荐之插件Autopep8
- proxool配置多数据库多连接池
- 程序员最讨厌的9句话
- Python学习笔记九:文件I/O
- 用 Graphviz+pvtrace 可视化函数调用
- CentOS 7 + Win 双系统的安装遇到的重要问题
- 下载XAMPP并安装和使用(Mac环境)
- 你焊接过最小的贴片器件是多大?
- GNU C Complier - GNU Compiler Collection - GCC
- UOJ#449. 【集训队作业2018】喂鸽子(期望dp)
- 参加计算机培训典型材料,计算机应用专业典型学员事迹材料
- Google 推出浏览器版Google Voice
- 使用BDC进行Miro录屏时的公司代码弹窗问题
- vue-router.esm-bundler.js?6c02:1474 Uncaught TypeError: Cannot read property ‘forEach‘ of undefined
- Arduino基础篇(七)-- 如何使用DS18B20数字温度传感器(基于OneWire和DallasTemperature库)
热门文章
- iOS开发-Interface Builder的前世今生
- linux系统有哪些电脑,低配电脑装linux系统好吗,或者有什么别的系统推荐吗?...
- Git冲突解决之P4Merge
- 微信小程序——editor显示html和生成html、用parser显示html文本
- 豆瓣评分小程序Part-1
- 安卓手机当做电脑摄像头使用,Android 8.0 + Win10亲测可用
- 学了三年的PS 全部在这里了,都是精华(photoshop常用操作)
- Unity3d 性能优化篇
- 电商产品设计:后台营销功能模块设计-砍价活动(二)
- NAT SIP helper