MySQL索引优化之不适合构建索引及索引失效的几种情况详解

目录
  • 结论
  • 不建议建立索引的场景
  • 索引失效的场景
  • 小结

结论

具体案例下文有详尽描述

不适合建立索引的场景:

  • 数据量比较小的表不建议建立索引
  • 有大量重复数据的字段上不建议建立索引(类似:性别字段)
  • 需要进行频繁更新的表不建议建立索引
  • where、group by、order by后面的没有使用到的字段不建立索引
  • 不要定义冗余索引

索引失效的场景:

  • 过滤条件使用不等于(!=、<>)
  • 过滤条件使用is not null
  • 在索引字段上使用函数或进行计算
  • 在使用联合索引的时候,需要满足“最佳左前缀法则”,否则失效
  • 当使用了类型转换也会导致索引失效
  • 在使用范围查询的时候,联合索引的部分字段失效(where age >18)
  • 在like字段中,如果是以%开头,索引失效(where name like ‘%abc’)
  • 在使用or进行查询的时候,or前后出现非索引字段,索引失效
  • 表和库的字符集不一致,回导致索引失效

知识点:

  • 每张表的索引不建议超过6个(占用空间、降低表更新速度)
  • 最终到底是否使用索引还是优化器进行决定的
  • 优化器会根据数据量、数据库版本、数据选择读进行查询代价的比较,从而决定是否使用索引
  • 建立索引的时候将需要范围匹配的字段建立在索引的尾部,避免失效
  • 在建立表的时候将字段设置为not null同时设置默认值,当需要查找没有值的记录的时候就可以使用where xxx = 默认值,放置使用is not null导致索引失效
  • 页面搜索的时候严谨左模糊或者全模糊(like ‘%abc’)
  • 对于过滤性较好的字段建立在联合索引的前面,这样就可以优先过滤比较多的数据

不建议建立索引的场景

场景一:数据少的表

当数据比较少的时候,索引的优势就不明显了,因为数据库的存储引擎也是非常快的,相较于需要查询索引在进行回表操作,可能直接查询的性能会更高一些,所以数据相对较少的表不建议建立索引

场景二:有大量重复数据的字段

类似于性别字段,只有“男”和“女”两个不同的值,所以索引一半的数据是“男”一半的数据是“女”,那么建立索引并不能进行快速的查询等,所以不建议在有大量重复数据的列上建立索引

场景三:频繁更新的表(update/delete/insert)

因为表中更新数据的时候,索引也是需要进行对应的维护的,如果一个表近期需要频繁的进行增删改操作,那么就需要耗费大量的时间去维护索引,不建议建立索引,可以在需要进行频繁的更新操作的时候将索引删除,更新完毕之后重建索引

场景四:没有使用的字段(where/group by/order by)

不是where/group by/order by后面的字段没有必要建立索引,因为不会使用到该索引

场景五:不要定义冗余索引

create index username_password_address on xiao(username,password,address);
-- 如果建立了第一个索引,那么就没有必要建立第二个索引
create index username on xiao (username);
--第二个索引就是冗余索引,因为第一个已经是先根据username排序的索引
--也就是第二个索引的功能完全可以由第一个索引实现

这里因为username作为第一个联合索引的第一个字段,所以索引就是按照username进行排序,在username相同的情况下按照password、address排序,所以也就是实现了单独拿username列作为索引的功能,即第二个索引就是多余的

索引失效的场景

场景一:在建立索引的字段上进行运算(函数等),导致索引失效

这里首先是给age创建了索引,在第一次查询过程中使用了age索引,但是第二次key值为null(索引失效),导致索引失效的原因在于第二次查询的时候where后面对age进行了计算,计算机并不知道执行的是什么计算所以会将age+1计算后与1比较,索引失效

类似于在字段上使用函数concat()等都会导致索引失效

场景二:使用不等于(where age != 18)

当使用等值运算,那么是可以在索引中进行查找的,但是如果是不等于,那么则需要遍历所有数据,所以所失效

explain select * from xiaoyuanhao where age = 18;
explain select * from xiaoyuanhao where age != 18;
--这里是在age字段上建立了普通索引,第二个查询时候索引失效

场景三:使用is not null索引失效

与不等于一样,如果使用的是is not null,那么就需要进行全部数据的遍历操作,索引失效,但是如果使用的是is null那么依旧是可以使用索引的

--这里是在age字段上建立了普通索引,第二个查询时候索引失效
explain select * from xiaoyuanhao where age is null;
--可以正常使用索引
explain select * from xiaoyuanhao where age is not null;
--索引失效

场景四:在使用联合索引的时候没有遵循最佳左前缀法则

CREATE INDEX age_classid_name ON student(age,classId,NAME);
EXPLAIN SELECT * FROM student WHERE classId = 30 AND NAME = 'xiaoyuanhao';
-- 因为没有使用age字段,所以没有准许最佳左前缀原则,索引失效

从这里可以看出是没有使用索引的(key = null),因为创建的索引是先按照age进行排序,在age相同的情况下按照classId和name排序,如果在查询的时候需要直接按照classId进行排序查找,那么就无法使用该索引,即索引失效。

如果需要使用使用索引,那么就一定需要到联合索引的第一个字段age,案例如下

EXPLAIN SELECT * FROM student WHERE age = 10 AND NAME = 'xiaoyuanhao';
EXPLAIN SELECT * FROM student WHERE age = 10 AND classId = 33 AND NAME = 'xiaoyuanhao';
--两者都是使用age字段索引,所以索引有效

场景五:类型转换导致索引失效

CREATE INDEX NAME ON student(NAME);
-- 这里的name字段是varchar类型
EXPLAIN SELECT * FROM student WHERE NAME = 'xiao';
-- 本次查询是可以使用索引的,因为类型都是一致的,都是字符串
EXPLAIN SELECT * FROM student WHERE NAME = 123;
-- 本次查询则无法使用索引,因为是将数字类型123转换为字符类型

没有发生类型转换,使用索引key = name

发生了类型转换,无法使用索引kye = null,索引失效

使用索引的时候一定需要保证数据类型是一致的,否则系统就需要进行转换,那么就无法使用索引

场景六:使用范围查询导致联合索引其他字段失效

create index age_classId_name on student (age,classId,name);
EXPLAIN SELECT * FROM student WHERE age = 10 AND classId > 20 AND NAME = 'xiaoyuanhao';
-- 这里只能使用age,classId,索引的前两个字段
EXPLAIN SELECT * FROM student WHERE age = 10 AND classId = 20 AND NAME = 'xiaoyuanhao';
-- 这里可以使用完整的索引,因为都是等值连接

在classId字段上使用范围查询,导致name字段失效,有效索引长度为63

使用的都是等值匹配,整个索引皆可用,有效索引长度为73

也就是在对于联合索引来说,如果在使用的时候是等值匹配,那么就可以重复的利用索引,如果不是等值匹配,那么该字段也是可以使用索引的,但是该字段右边的字段就将失效

建议在建立索引的时候将需要范围匹配的字段建立在索引的最后面

场景七:在使用like的时候,如果以%开头导致索引失效

EXPLAIN SELECT * FROM student WHERE NAME LIKE 'abc%';
-- 可以正常使用索引
EXPLAIN SELECT * FROM student WHERE NAME LIKE '%abc';
-- 这里在like中,%在前面无法使用索引

key = name,使用了该索引,索引有效

key = null,索引失效

因为建立的索引实际上是按照整个字符串的从第一个开始进行比较排序的,所以在使用like的时候,也只能够重现进行比较,如果使用的是’%abc’,那么查询的就是以abc结尾的数据,无法使用索引

场景八:or前后出现非索引字段,索引失效

-- 该表中只有name字段上的索引
CREATE INDEX NAME ON student(NAME);
EXPLAIN SELECT * FROM student WHERE NAME = 'xiao';
-- 这里是可以使用name索引的
EXPLAIN SELECT * FROM student WHERE NAME = 'xiao' OR classId = 1001;
-- 这个则无法使用索引,进行的是全表扫描

key = null,无法使用索引,or条件中出现非索引字段

因为如果name不等于’xiao’的时候那么就会继续判断classId是否等于1001,那么实际上还是会进行全表扫描,所以索引失效(也就是进行name判断的时候可以使用索引,但是在判断classId的时候又要全表扫描,那么优化器就直接进行全表扫描),但是如果or前后的字段都有索引了,那么就就会使用索引

小结

在建立索引的时候,尽量要避免出现以上的情况导致索引失效,但是就算建立的索引是正确的、有效的,但是在不同的数据量以及数据库版本的情况下,执行的结果也是不一致的,如果想了解哪些情况下适合建立索引,可以从以下文章中进行交流MySQL索引优化之适合构建索引的几种情况详解

到此这篇关于MySQL索引优化之不适合构建索引及索引失效的几种情况详解的文章就介绍到这了,更多相关MySQL索引优化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Mysql索引分类及其使用实例详解

    目录 Mysql的索引分类 单列索引 创建单列索引的几种方式: 唯一索引 创建唯一索引的几种方式: 联合索引(复合索引) 创建联合索引(复合索引)的方式: Mysql的索引类型 INDEX | NORMAL 普通索引 UNIQUE 唯一索引 PRIMARY KEY 主键索引 FULLTEXT 全文索引 SPATIAL 空间索引 Mysql的索引方法 BTREE HASH Mysql的索引使用示例 单列索引使用示例 复合索引使用示例 Mysql的索引分类 MySQL 索引MySQL索引的建立对于M

  • MySQL添加索引特点及优化问题

    目录 一.索引的特点 二.索引类型 1.FULLTEXT 2.HASH 3.BTREE 4.RTREE 三.索引种类 四.索引的使用策略 1.什么时候要使用索引? 2.什么时候不要使用索引? 3.索引失效的情况? 4.mysql查询优化? 5.索引的常见问题 一.索引的特点 当MySQL单表记录数过大时,增删改查性能都会急剧下降.MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度.除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑.

  • 哪些情况会导致 MySQL 索引失效

    目录 前言 创建测试表和数据 索引失效情况1:非最左匹配 索引失效情况2:错误模糊查询 索引失效情况3:列运算 索引失效情况4:使用函数 索引失效情况5:类型转换 索引失效情况6:使用 is not null 总结 前言 为了验证 MySQL 中哪些情况下会导致索引失效,我们可以借助 explain 执行计划来分析索引失效的具体场景. explain 使用如下,只需要在查询的 SQL 前面添加上 explain 关键字即可,如下图所示: 而以上查询结果的列中,我们最主要观察 key 这一列,ke

  • MySQL 回表,覆盖索引,索引下推

    目录 回表 覆盖索引 索引下推 无索引下推: 查看索引下推的状态 有索引下推: 开启索引下推 回表 在研究mysql二级索引的时候,发现Mysql回表这个操作,往下研究了一下 字面意思,找到索引,回到表中找数据 解释一下就是: 先通过索引扫描出数据所在的行,再通过行主键ID 取出数据. 举个例子说明: SELECT * FROM INNODB_USER WHERE AGE = 18 AND USER_NAME LIKE '模糊查%'; 假如age和user_name两个字段是个联合索引,我们通过

  • mysql 索引使用及优化详情

    目录 前言 mysql索引原理 mysql索引分类 索引创建语法 1.创建索引 2.查看索引 3.删除索引 4.为 username和password创建联合索引 5.给user表添加一个info的字段,并为这个字段添加全文索引 已经存在的表创建.删除索引等 1.使用ALTER TABLE语句创建索引 2.使用ALTER TABLE语句删除索引 常用的索引设计原则 索引失效情况总结 尽量使用覆盖索引 前言 索引对有一定开发经验的同学来说并不陌生,合理使用索引,能大大提升sql查询的性能,可以这么

  • MySQL细数发生索引失效的情况

    目录 索引的存储结构 不合理的模糊查询条件 对索引使用函数 对索引进行表达式计算 对索引使用隐式转换 联合索引非最左匹配 where子句中的or 总结 索引的存储结构 首先了解一下索引的存储结构,知道了索引的存储结构,才方便我们更好地理解索引失效的问题. 索引的存储结构跟MySQL的存储引擎有关,存储引擎的不同采用的结构也会不同. MySQL默认的存储引擎InnoDB采用B+Tree作为索引的数据结构,在创建表时,InnoDB会默认创建一个主键索引,这是一个聚簇索引,其他索引都属于二级索引. M

  • MySQL索引失效场景及解决方案

    目录 一.前言 二.最左前缀匹配原则 三.MySQL逻辑架构和优化器 四.索引失效场景以及为何会失效 五.总结 一.前言 在对SQL语句进行索引查询时会遇到索引失效的时候,对于该语句的可行性以及性能效率方面有至关重要的影响,本篇剖析索引为何失效,有哪些情况会导致索引失效以及对于索引失效时的优化解决方案,其中着重介绍最左前缀匹配原则.MySQL逻辑架构和优化器.索引失效场景以及为何会失效. 二.最左前缀匹配原则 之前有写了一篇关于MySQL添加索引特点及优化问题方面的文章,下面将介绍索引失效的相关

  • MySql索引和事务定义到使用全面涵盖

    目录 索引是什么 索引的使用场景 索引的常见操作 索引背后的数据结构 事务是什么 事务的基本特性 小结 索引是什么 索引是一种特殊的文件,包含着对数据表里所有记录的引用指针.可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现.索引就相当于一本书的目录,通过索引 可快速定位.检索数据.使用索引大大提高了查找效率,但同时索引也占用了更多的空间,拖慢了增删改的速度. 索引的使用场景 1.数据量较大,且经常对这些列进行条件查询. 2.该数据库表的插入操作,及对这些列的修改操作

  • MySQL索引优化之适合构建索引的几种情况详解

    目录 结论 建立索引的场景 小结 结论 在where后面的过滤字段上建立索引(select/update/delete后面的where都是适用的),使用索引加快过滤效率,不用进行全表扫描 在具有唯一要求的字段上添加唯一索引,加快查询效率,查到即可直接返回 group by或者order by后面的字段添加索引,由于索引是排好序的,所以建立索引就等同于在查询之前已经是排好序了(这里需要注意建立的联合索引建立中字段的顺序,可以结合具体案例场景7进行学习) 在DISTINCT(去重字段)后面的字段添加

  • MySQL索引优化之不适合构建索引及索引失效的几种情况详解

    目录 结论 不建议建立索引的场景 索引失效的场景 小结 结论 具体案例下文有详尽描述 不适合建立索引的场景: 数据量比较小的表不建议建立索引 有大量重复数据的字段上不建议建立索引(类似:性别字段) 需要进行频繁更新的表不建议建立索引 where.group by.order by后面的没有使用到的字段不建立索引 不要定义冗余索引 索引失效的场景: 过滤条件使用不等于(!=.<>) 过滤条件使用is not null 在索引字段上使用函数或进行计算 在使用联合索引的时候,需要满足“最佳左前缀法则

  • SQL索引失效的11种情况详析

    目录 索引失效案例 [1]. 全值匹配 [2]. 最佳左前缀法则 [3]. 主键插入顺序 [4]. 计算.函数.类型转换(自动或手动)导致索引失效 [5]. 类型转换导致索引失效 [6]. 范围条件右边的列索引失效 [7]. 不等于(!= 或者<>)索引失效 [8]. is null可以使用索引,is not null无法使用索引 [9]. like以通配符%开头索引失效 [10]. OR 前后存在非索引的列,索引失效 [11]. 数据库和表的字符集统一使用utf8mb4 总结 数据库调优的大

  • MySQL索引失效的几种情况详析

    1.前导模糊查询不能利用索引(like '%XX'或者like '%XX%') 假如有这样一列code的值为'AAA','AAB','BAA','BAB' ,如果where code like '%AB'条件,由于前面是 模糊的,所以不能利用索引的顺序,必须一个个去找,看是否满足条件.这样会导致全索引扫描或者全表扫 描.如果是这样的条件where code like 'A % ',就可以查找CODE中A开头的CODE的位置,当碰到B开头的 数据时,就可以停止查找了,因为后面的数据一定不满足要求.

  • MySQL性能优化之如何高效正确的使用索引

    实践是检验真理的唯一途径,本篇只是站在索引使用的全局来定位的,你只需要通读全篇并结合具体的例子,或回忆以往使用过的地方,对整体有个全面认识,并理解索引是如何工作的,就可以了.在后续使用索引,或者优化索引时,可以从这些方面出发,进一步来加深对索引正确高效的使用. 一.索引失效 索引失效,是一个老生常谈的话题了.只要提到数据库优化.使用索引,都能一口气说出一大堆索引失效的场景,什么不能用.什么不该用这类的话,在此,我就不再一一罗列啰嗦了. 索引失效,是指表中有字段创建了索引,由于sql语句书写不当导

  • MySQL索引失效的几种情况汇总

    一.索引不存储null值 更准确的说,单列索引不存储null值,复合索引不存储全为null的值.索引不能存储Null,所以对这列采用is null条件时,因为索引上根本 没Null值,不能利用到索引,只能全表扫描. 为什么索引列不能存Null值? 将索引列值进行建树,其中必然涉及到诸多的比较操作.Null值的特殊性就在于参与的运算大多取值为null. 这样的话,null值实际上是不能参与进建索引的过程.也就是说,null值不会像其他取值一样出现在索引树的叶子节点上. 二.不适合键值较少的列(重复

  • MySQL导致索引失效的几种情况

    目录 一.准备工作 二.索引失效规则 1.优先使用联合索引 2.最左匹配原则 3.范围条件右边的列索引失效 4.计算.函数导致索引失效 5.类型转换导致索引失效 6.不等于(!= 或者<>)索引失效 7.is null可以使用索引,is not null无法使用索引 8.like以%开头,索引失效 9.OR前后存在非索引的列,索引失效 10.字符集不统一 三.建议 一.准备工作 首先准备两张表用于演示: CREATE TABLE `student_info` ( `id` int NOT NU

  • 优化Tomcat配置(内存、并发、缓存等方面)方法详解

    Tomcat有很多方面,我从内存.并发.缓存等方面介绍优化方法. 一.Tomcat内存优化 Tomcat内存优化主要是对 tomcat 启动参数优化,我们可以在 tomcat 的启动脚本 catalina.sh 中设置 java_OPTS 参数. JAVA_OPTS参数说明 server 启用jdk 的 server 版: -Xms java虚拟机初始化时的最小内存: -Xmx java虚拟机可使用的最大内存: -XX: PermSize 内存永久保留区域 -XX:MaxPermSize 内存最

  • 用 Python 连接 MySQL 的几种方式详解

    尽管很多 NoSQL 数据库近几年大放异彩,但是像 MySQL 这样的关系型数据库依然是互联网的主流数据库之一,每个学 Python 的都有必要学好一门数据库,不管你是做数据分析,还是网络爬虫,Web 开发.亦或是机器学习,你都离不开要和数据库打交道,而 MySQL 又是最流行的一种数据库,这篇文章介绍 Python 操作 MySQL 的几种方式,你可以在实际开发过程中根据实际情况合理选择. 1.MySQL-python MySQL-python 又叫 MySQLdb,是 Python 连接 M

  • 使用Go基于WebSocket构建千万级视频直播弹幕系统的代码详解

    (1)业务复杂度介绍 开门见山,假设一个直播间同时500W人在线,那么1秒钟1000条弹幕,那么弹幕系统的推送频率就是: 500W * 1000条/秒=50亿条/秒 ,想想B站2019跨年晚会那次弹幕系统得是多么的NB,况且一个大型网站不可能只有一个直播间! 使用Go做WebSocket开发无非就是三种情况: 使用Go原生自带的库,也就是 golang.org/x/net ,但是这个官方库真是出了奇Bug多 使用GitHub大佬 gorilla/websocket 库,可以结合到某些Web开发框

随机推荐