MySQL 索引失效场景

左侧模糊查询

模糊查询时(like语句),模糊匹配的占位符位于条件的首部

B+树索引的键值都是排序的,而条件的左侧使用了占位符,会导致无法按照正常的目录进行匹配,从而导致索引失效

select * from tmp where nick like '%张';

OR操作

  1. OR查询中有一个非索引字段
---id为主键,nick未创建索引
select * from tmp where id = 1 or nick = '张一';
  1. OR查询同时使用><
select * from tmp where id  > 1 or id  < 100;

联合索引不满足最左前缀原则

在联合索引的场景下,查询条件不满足最左匹配原则

KEY `idx_uid_nick` (`uid`,`nick`)

走联合索引

---满足最左匹配原则
select * from tmp where uid = 1;
select * from tmp where uid = 1 and nick = '张一';

全表查询

select * from tmp where nick = '张一';

索引列参与运算

索引列参与运算,如加减乘除,会导致数据库需要全表查询出所有字段值,对其计算后与参数值进行比较。

select * from tmp where id + 1 = 2;

优化方式:进程内存计算/SQL查询条件右侧计算

--- 内存计算,得知要查询的id为1
select * from tmp where id = 1;
--- 参数侧计算
select * from tmp where id = 2 - 1;

不等于比较

查询条件使用不等进行比较时,需要慎重,普通索引会查询结果集占比较大时索引会失效

---走索引
select * from tmp where id != 1;
---不走索引
select * from tmp where uid <> 1;

NULL值

MySQL不对NULL值进行索引创建,判断IS NULLIS NOT NULL可能会导致索引失效

MySQL建议最好设置为NOT NULL,需要使用NULL的情况使用DEFAULT VALUE代替

select * from tmp where nick IS NOT NULL;

内置函数

索引列参与了MySQL内置函数,会导致全表扫描,索引失效

select * from tmp where date_add(create_time, INTERVAL 1 DAY) = '2022-07-30 00:00:00';

类型隐式转换

参数类型与字段类型不匹配,导致MySQL使用了convert函数进行了类型隐式转换,导致索引失效

---nick为varchar,SQL语句中使用int类型,将参数加上单引号可避免此情况
select * from tmp where nick = 2022;

SELECT *

在《阿里巴巴开发手册》的ORM映射章节中有一条【强制】的规范:
【强制】在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。 说明:

  1. 增加查询分析器解析成本。
  2. 增减字段容易与resultMap配置不一致。
  3. 无用字段增加网络消耗,尤其是text类型的字段。
KEY `idx_uid_nick` (`uid`,`nick`)

需要回表查询

select * from tmp where uid = 1 and nick = '张一';

走覆盖索引,无需回表进行主键查询

select uid, nick from tmp where uid = 1 and nick = '张一';

MySQL优化器策略

Mysql优化器的其他优化策略,比如优化器认为在某些情况下,全表扫描比走索引快,则它就会放弃索引

索引相关

key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)

不损失精确性的情况下,长度越短越好

key_len的计算:id_no类型为varchar(18),字符集为utf8mb4_bin,也就是使用4个字节来表示一个完整的UTF-8。此时,key_len= 18*4=72;
由于该字段类型varchar为变长数据类型,需要再额外添加2个字节。此时,key_len = 72 + 2 = 74;
由于该字段运行为NULL(default NULL),需要再添加1个字节。此时,key_len = 74 + 1 = 75;

离散读

MySQL优化器使用了全表扫描,而非辅助索引

select * from tmp where uid > 1 and uid < 100000;

具体原因是查询结果为整行信息,若走辅助索引需要回表操作到聚集索引中查询完整数据。虽然辅助索引中数据是顺序存放的,但是再一次进行书签查找的数据则是无序的,因此变为了磁盘上的离散读操作。

如果要求访问的数据量很小,则优化器还是会选择辅助索引,但是当访问的数据占整个表中数据的蛮大一部分时(一般是20%左右),优化器会选择通过聚集索引来查找数据。

优化器优化离散读

MySQL 5.6之前,优化器在进行离散读决策的时候,如果数据量比较大,会选择使用聚集索引,全表扫描。
MySQL5.6版本开始支持Multi-Range Read(MRR/MR2)优化。

Multi-Range Read优化的目的就是为了减少磁盘的随机访问,并且将随机访问转化为较为顺序的数据访问,这对于IO-bound类型的SQL查询语句可带来性能极大的提升。Multi-Range Read优化可适用于range,ref,eq_ref类型的查询。

MR2优化的优点:

  • 使数据访问变得较为顺序
    在查询辅助索引时,首先根据得到的查询结果,按照主键进行排序,并按照主键排序的顺序进行书签查找。
  • 减少缓冲池中页被替换的次数
    顺序查找可以对一个页进行顺序查找,无需离散加载数据页
  • 批量处理对键值的查询操作

对于InnoDB和MyISAM存储引擎的范围查询和JOIN查询操作,MR2的工作方式如下:

  1. 将查询得到的辅助索引键值存放于一个缓存中,这时缓存中的数据是根据辅助索引键值排序的
  2. 将缓存中的键值根据RowID进行排序
  3. 据RowID的排序顺序来访问实际的数据文件

ICP优化

Index Condition Pushdown(ICP)同样是MySQL 5.6开始支持的一种根据索引进行查询的优化方式。

在支持ICP后,MySQL数据库会在取出索引的同时,判断是否可以进行WHERE条件的过滤,也就是将WHERE的部分过滤操作放在了存储引擎层。
在某些查询下,可以大大减少上层SQL层对记录的索取(fetch),从而提高数据库的整体性能。ICP优化支持range、ref、eq_ref、ref_or_null类型的查询,当前支持MyISAM和InnoDB存储引擎。
当优化器选择ICP优化时,可在执行计划的Extra列看到Using index condition提示。

不适合建索引的字段

  1. 数据唯一性差的字段
    比如性别,只有两种可能数据。意味着索引的二叉树级别少,多是平级。这样的二叉树查找无异于全表扫描。

  2. 频繁更新的字段
    比如loginCount登录次数,频繁变化导致索引也频繁变化,增大数据库工作量,降低效率。

  3. 字段不在查询条件内
    字段不在where语句出现时不要添加索引。如果where后含IS NULL/IS NOT NULL/like '%s%'等条件,不建议使用索引


参考资料:

  1. 《MySQL技术内幕 InnoDB存储引擎》
  2. MySQL 索引的数据结构及类型
  3. 15个必知的Mysql索引失效场景,别再踩坑了!
  4. MySQL第二弹
  5. 离散读、ICP优化、全文检索

MySQL 索引优化及失效场景相关推荐

  1. MySQL索引优化分析

    转载来源:https://www.cnblogs.com/itdragon/p/8146439.html MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学 ...

  2. 深入理解MYSQL索引优化:多列索引

    索引是什么 是存储引擎用于找到数据的一种数据结构. C/C++ Linux服务器开发高级架构视频点击:C/C++Linux服务器开发高级架构师/Linux后台架构师-学习视频 MYSQL索引优化视频详 ...

  3. 十几年老Java咳血推荐:MySQL索引原理、失效情况,两万字肝爆,建议收藏!

    一.前言 MySQL 作为主流的数据库,是各大厂面试官百问不厌的知识点,但是需要了解到什么程度呢?仅仅停留在 建库.创表.增删查改等基本操作的水平可不够.在面试后端开发的时候,一连几个问题,简直会被问 ...

  4. MySQL第8天:MySQL索引优化分析之SQL慢

    MySQL索引优化分析之SQL慢 #编写时间:2017.3.11 #编写地点:广州 性能下降SQL慢,执行时间长,等待时间长的原因有: (1)查询语句写的不合理 (2)索引失效:单值索引.符合索引 ( ...

  5. MySQL索引原理、失效情况

    声明:本文是小编在学习过程中,东拼西凑整理,如有雷同,纯属借鉴. Mysql5.7的版本, InnoDB引擎 目录 1 mysql索引知识 1.1 B+Tree索引 1.2 主键索引和普通索引的区别 ...

  6. 不清楚MySQL索引为什么会失效,面试官:回去等通知

    作为一名程序员,在求职面试时,不知你有没有遇到类似这样的问题. 张工是一名java程序员,最近到一家软件公司应聘软件开发岗位,面试官问了他关于MySql索引这样的一个问题. 面试官:为什么MySQL字 ...

  7. mysql索引优化有几种_mysql索引优化

    索引类型 从物理存储角度上,索引可以分为聚集索引和非聚集索引. 1.聚集索引(Clustered Index) 聚集索引决定数据在磁盘上的物理排序,一个表只能有一个聚集索引. 2.非聚集索引(Non- ...

  8. mysql高级篇(二)mysql索引优化分析

    mysql高级篇笔记 mysql高级篇(一)mysql的安装配置.架构介绍及SQL语句的复习. mysql高级篇(二)mysql索引优化分析. mysql高级篇(三)查询截取分析(慢查询日志).主从复 ...

  9. MySQL第12天:MySQL索引优化分析之性能优化案例实践

    MySQL索引优化分析之性能优化案例实践 执行计划中各select_type含义可以看:MySQL第11天:MySQL索引优化分析之性能分析 https://weibo01.blog.csdn.net ...

最新文章

  1. 通用社区登陆组件技术分享(开源)中篇:OAuth 登陆组件流程及组件集成方法...
  2. Dijkstra算法的另一种证明
  3. Oracle使用游标
  4. 王道计算机网络 应用层整理 超详细版
  5. 盘点技术史:流量运营(PC 时代)
  6. 【Python】ffmpeg模块处理视频、音频信息
  7. SpringBoot + Vue 开发前后端分离的旅游管理系统
  8. Django运算表达式与Q对象/F对象
  9. 在DOS中使用系统还原工具
  10. 190415每日一句
  11. [.NET] EF LINQ 按时间对数据分类汇总
  12. pdf转cad怎么弄_还在为cad转pdf烦恼吗?教你CAD批量转pdf
  13. 日知录(九):PR视频剪辑Creo
  14. 中医基础理论第二章藏象(心)
  15. 数据库设计的阶段任务
  16. 思维导图网页版推荐,这两个网站建议收藏
  17. 旋转变换,变换后改变图片大小
  18. WinUSB安装以及与Linux通讯
  19. PPT基础(三十)图片的特殊效果
  20. 使用python turtle库13行代码实现奥运五环

热门文章

  1. echarts地图文字重叠解决方案_echarts地图自适应中出现重叠错位的两个地图问题排查...
  2. python发微信红包群二维码_小伙利用Python群发“支付宝”红包短信,一天赏金可达上千元...
  3. ipa文件上架appstore步骤
  4. 一位内核开发者的见闻
  5. 服务器安全设置技术实例WindowsServer2003_+_IIS6.0_+_ASP_+_NET
  6. TS流PAT、PMT、SDT内容
  7. html如何自动打开手机微信支付,微信支付分正式上线!微信支付分开通教程
  8. FlexibleLayout
  9. Windows下100个CMD常用命令(2)
  10. Node.js+Socket.io实现双人在线五子棋对战