查询条件有 or

假设在 customer_name 字段设置了普通索引,执行以下 sql:

# type: ref, possible_keys: idx_customer_name, key: idx_customer_name
# idx_customer_name 索引生效
explain select id, customer_name, company_name from t_user_info where customer_name = 'test_name' # type: ref, possible_keys: idx_customer_name, key: idx_customer_name
# idx_customer_name 索引生效
explain select id, customer_name, company_name from t_user_info where customer_name = 'test_name' and company_name = 'test_name' # type: all, possible_keys: idx_customer_name, key: null
# idx_customer_name 索引不生效,使用全表扫描
explain select id, customer_name, company_name from t_user_info where customer_name = 'test_name' or company_name = 'test_company'

like 查询以 % 开头

假设在 customer_name 字段设置了普通索引,执行以下 sql:

# type: all, possible_keys: null, key: null
# idx_customer_name 索引不生效
explain select id, customer_name, company_name from t_user_info where customer_name like '%name' # type: range, possible_keys: idx_customer_name, key: idx_customer_name
# idx_customer_name 索引生效
explain select id, customer_name, company_name from t_user_info where customer_name like 'test%'

如果希望以 % 开头仍使用索引,则需要使用覆盖索引,即只查询带索引字段的列

# type: index, possible_keys: null, key: idx_customer_name
# idx_customer_name 索引生效
# id 是主键,idx_customer_name 构成的 b+tree 除了有 customer_name,也包含用于指向对应行的 id
explain select id, customer_name from t_user_info where customer_name like '%name'

索引列参与运算

假设 id 字段为主键,执行以下 sql:

# type: const, possible: primary, key: primary
# idx_id 索引生效
explain select id, customer_name, company_name from t_user_info where id = 2 # type: all, possible: null, key: null
# idx_id 索引不生效
explain select id, customer_name, company_name from t_user_info where id + 1 = 2

索引列使用函数

假设在 customer_name 字段设置了普通索引,执行以下 sql:

# type: ref, possible_keys: idx_customer_name, key: idx_customer_name
# idx_customer_name 索生效
explain select id, customer_name, company_name from t_user_info where customer_name = '查理一世' # type: all, possible_keys: null, key: null
# idx_customer_name 索引不生效
explain select id, customer_name, company_name from t_user_info where substr(customer_name, 1, 3) = '查理一'

类型转换

假设在 customer_name 字段设置了普通索引,执行以下 sql:

# type: all, possible_keys: idx_customer_name, key: null
# idx_customer_name 索引不生效
explain select id, customer_name, company_name from t_user_info where customer_name = 10

这是因为 mysql 会自动对字段执行类型转换函数,如上 sql 相当于

select id, customer_name, company_name from t_user_info where cast(customer_name as signed) = 10

两列做比较

如果两个列数据都有索引,但在查询条件中对两列数据进行了对比操作,则会导致索引失效

假设在 customer_name、company_name 字段设置了普通索引,执行以下 sql,仅作示例:

# type: range, possible_keys: idx_customer_name, key: idx_customer_name
# idx_customer_name 索引生效
explain select id, customer_name, company_name from t_user_info where customer_name > '查理一世' # type: all, possible_keys: null, key: null
# idx_customer_name 索引生效
explain select id, customer_name, company_name from t_user_info where customer_name > company_name

联合索引不满足最左匹配原则

联合索引遵从最左匹配原则,所谓最左匹配原则,就是如果 SQL 语句用到了联合索引中的最左边的索引,那么这条 SQL 语句就可以利用这个联合索引去进行匹配。值得注意的是,当遇到范围查询(>、<、between、like)时就会停止匹配

假设对 a、b、c 字段建立联合索引 idx_a_b_c,执行 sql 如下:

# type: ref, possible_keys: idx_a_b_c, key: idx_a_b_c, ref: const
# idx_a_b_c 索引生效,a 字段能用到索引
explain select * from test_table where a = 1 # type: ref, possible_keys: idx_a_b_c, key: idx_a_b_c, ref: const, const
# idx_a_b_c 索引生效,a、b 字段能用到索引
explain select * from test_table where a = 1 and b = 2 # type: ref, possible_keys: idx_a_b_c, key: idx_a_b_c, ref: const, const, const
# idx_a_b_c 索引生效,a、b、c 字段能用到索引
explain select * from test_table where a = 1 and b = 2 and c = 3 # type: ref, possible_keys: idx_a_b_c, key: idx_a_b_c, ref: const, const, const
# idx_a_b_c 索引生效,a、b、c 字段能用到索引,优化器会调整 a、b、c 的顺序,从而用上索引
explain select * from test_table where b = 2 and c = 3 and a = 1 # type: range, possible_keys: idx_a_b_c, key: idx_a_b_c, ref: null, key_len: 75
# a 字段类型为 varchar(18),字符集为 utf8mb4,1 个字符占 4 个字节,占用 4*18=72 字节
# varchar 为变长数据类型,额外占用 2 个字节
# 字段默认为 null,额外占用 1 个字节
# 因此 key_len = 72 + 2 + 1 = 75,可判断 idx_a_b_c 索引生效,但只有 a 字段用到索引
explain select * from test_table where a > 1 and b = 2 and c = 3

我们知道索引是用 B+Tree 实现的,如果只对 a 字段建立普通索引,那么 B+Tree 根据 a 字段排序。如果对 a、b、c 建立联合索引,那么首先根据 a 字段排序,如果 a 字段值相同,再根据 b 字段排序,如果 b 字段值也相同,再根据 c 字段排序。因此,使用联合索引必须按照从左到右,也就是字段排序的顺序,只有先用了 a,才能接着使用 b,使用了 b 才能接着使用 c

MySQL 索引失效场景总结的更多相关文章

  1. Mysql 索引失效场景

    例如:一张USER表   有字段属性 name,age   其中name为索引 下面列举几个索引失效的情况 1. select * from USER where name=‘xzz’ or age= ...

  2. 《MySQL面试小抄》索引失效场景验证

    我是肥哥,一名不专业的面试官! 我是囧囧,一名积极找工作的小菜鸟! 囧囧表示:小白面试最怕的就是面试官问的知识点太笼统,自己无法快速定位到关键问题点!!! 本期主要面试考点 面试官考点之什么情况下会索 ...

  3. MySQL索引失效的常见场景

    当然请记住,explain是一个好习惯! MySQL索引失效的常见场景 在验证下面的场景时,请准备足够多的数据量,因为数据量少时,MySQL的优化器有时会判定全表扫描无伤大雅,就不会命中索引了. 1. ...

  4. MySQL索引失效之隐式转换

    常见索引失效: 1. 条件索引字段"不干净":函数操作.运算操作 2. 隐式类型转换:字符串转数值:其他类型转换 3. 隐式字符编码转换:按字符编码数据长度大的方向转换,避免数据截 ...

  5. 面试突击60:什么情况会导致 MySQL 索引失效?

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

  6. mysql索引总结(4)-MySQL索引失效的几种情况

    mysql索引总结(1)-mysql 索引类型以及创建 mysql索引总结(2)-MySQL聚簇索引和非聚簇索引 mysql索引总结(3)-MySQL聚簇索引和非聚簇索引 mysql索引总结(4)-M ...

  7. 面试题: MySQL 索引失效的10大原因

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.建表: CREATE TABLE staffs ( id INT PRIMARY KEY AUTO_ ...

  8. MySQL索引失效的几种场景

    我们都知道建立索引能够提高查询效率,那么是不是任何情况下都能提高呢,当然不是的的,下面我们就来列举一些常见的索引失效的场景. 借用上一篇文章的dm_person_info表 在card_code列没加 ...

  9. 3、MySQL 索引失效的场景

    索引失效的场景: 1.没有 where 条件 直接看 SQL 语句   2.where 条件中所在的列没有建立索引 show index from t;   3.从表中取得数据超过某个阈值.通常认为是 ...

  10. MySQL 索引失效-模糊查询,最左匹配原则,OR条件等。

    索引失效 介绍 索引失效就是我们明明在查询时的条件为索引列(包括自己新建的索引),但是索引不能起效,走的是全表扫描.explain 后可查看type=ALL. 这是为什么呢? 首先介绍有以下几种情况索 ...

随机推荐

  1. ORACLE查询优化及gather_plan_statistics hint

    查询优化手段和gather_plan_statistics hint: 在10g以后我们可以通过利用gather_plan_statistics提示来了解更多的SQL执行统计信息,具体使用方法如下: ...

  2. 《深入理解Java虚拟机》(八) 记录一次OOM问题分析实战

    目录 一.问题分析思路 二.主要问题概述以及分析 1.相关操作 2.主要问题现象 3.初步分析问题 三.相关工具介绍 四.实际问题快照分析 1.通过Memory查看老年代内存占用情况 2.选择Live ...

  3. 分享一个Github相关彩蛋

    楼上很多回答 都是基于手把手实操Github.Git源代码管理相关, 这些操作"无他,唯手熟尔". 今天提供一个github上阅读源码的小技巧,逆天级别的彩蛋. 要想成为大神,Gi ...

  4. 【Android逆向】frida hook so 函数

    1. apk来自52pojie 链接:https://pan.baidu.com/s/1vKC1SevvHfeI7f0d2c6IqQ 密码:u1an 2.apktool反编译apk,拿到so文件 ja ...

  5. Taurus.MVC WebMVC 入门开发教程3:数据绑定Model

    前言: 在这篇 Taurus.MVC WebMVC 入门开发教程的第三篇文章中, 我们将重点介绍如何进行数据绑定操作,还会学习如何使用 ${属性名称} CMS 语法来绑定页面上的元素与 Model 中 ...

  6. ASP.NET XML序列化

    整理一下ASP.NET里面如何序列化实体为XML,获取解析XML内容为实体. 第一步要添加程序集引用,项目-->引用-->鼠标右键-->添加引用-->选择程序集-->Sy ...

  7. 调试 Docker 容器内部进程

    首发于官方博客:https://nebula-graph.com.cn/posts/debug-nebula-graph-processes-docker/ 摘要:本文以 Nebula Graph 进 ...

  8. opencv库图像基础4绘图-python

    opencv库图像基础4绘图-python 1.绘画线条和简单图形 创建颜色字典和一个画布 import cv2 import numpy as np import matplotlib.pyplot ...

  9. Postman/Jmeter工具实现接口测试,为什么还要用代码来实现接口自动化测试?

    这种工具包括一些开源框架最大缺点就是不够灵活,如果是单接口的测试还行,但是有的项目接口比较庞大和负责,这种情况下就不大适用工具(工具适用于小型项目,代码适用于中大型项目) 主要有以下几个原因: 1敏捷 ...

  10. 第12章_MySQL数据类型

    目录: https://www.cnblogs.com/xjwhaha/p/15844178.html 1. MySQL中的数据类型 类型 类型举例 整数类型 TINYINT.SMALLINT.MED ...