MySQL索引优化原则和失效情况

news2024/9/28 23:23:33

目录

  • 1. 全值匹配
  • 2. 最佳左前缀法则
  • 3. 不要在索引列上做任何计算
  • 4. 范围之后全失效
  • 5. 尽量使用覆盖索引
  • 6. 使用不等于(!=或<>)会使索引失效
  • 7. is null 或 is not null也无法使用索引
  • 8. like通配符以%开头会使索引失效
  • 9. 字符串不加单引号导致索引失效
  • 10. 少用or,用or连接会使索引失效


1. 全值匹配

在这里插入图片描述

  • 创建表 插入数据
CREATE TABLE users(
  id INT PRIMARY KEY AUTO_INCREMENT,
  user_name VARCHAR(20) NOT NULL COMMENT '姓名',
  user_age INT NOT NULL DEFAULT 0 COMMENT '年龄',
  user_level VARCHAR(20) NOT NULL COMMENT '用户等级',
  reg_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间'
);

INSERT INTO users(user_name,user_age,user_level,reg_time)
VALUES('tom',17,'A',NOW()),('jack',18,'B',NOW()),('lucy',18,'C',NOW());

按索引字段顺序匹配使用。

xxxxxxxxxx
EXPLAIN SELECT * FROM users WHERE user_name = 'tom';

EXPLAIN SELECT * FROM users WHERE user_name = 'tom' AND user_age = 17

EXPLAIN SELECT * FROM users WHERE user_name = 'tom' AND user_age = 17 
AND user_level = 'A';

按顺序使用联合索引时, type类型都是 ref ,使用到了索引 效率比较高

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L96I1PWu-1688780333046)(.\img\07.jpg)]

2. 最佳左前缀法则

如果创建的是联合索引,就要遵循 最佳左前缀法则: 使用索引时,where后面的条件需要从索引的最左前列开始并且不跳过索引中的列使用。

  • 场景1: 按照索引字段顺序使用,三个字段都使用了索引,没有问题。

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_name = 'tom' 
    
    AND user_age = 17 AND user_level = 'A';
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j386Lpod-1688780333047)(.\img\04444.jpg)]

  • 场景2: 直接跳过user_name使用索引字段,索引无效,未使用到索引。

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_age = 17 AND user_level = 'A';
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-111H7Awo-1688780333047)(.\img\08.jpg)]

  • 场景3: 不按照创建联合索引的顺序,使用索引

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE 
    
    user_age = 17 AND user_name = 'tom' AND user_level = 'A';
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0IHrXbKh-1688780333048)(.\img\09.jpg)]

    where后面查询条件顺序是 user_age、user_level、user_name与我们建的索引顺序user_name、user_age、user_level不一致,为什么还是使用了索引,这是因为MySql底层优化器给咱们做了优化。

    但是,最好还是要按照顺序 使用索引。

最佳左前缀底层原理

​ MySQL创建联合索引的规则是: 首先会对联合索引最左边的字段进行排序 ( 例子中是 user_name ), 在第一个字段的基础之上 再对第二个字段进行排序 ( 例子中是 user_age )

​ 所以: 最佳左前缀原则其实是个B+树的结构有关系, 最左字段肯定是有序的, 第二个字段则是无序的(联合索引的排序方式是: 先按照第一个字段进行排序,如果第一个字段相等再根据第二个字段排序). 所以如果直接使用第二个字段 user_age 通常是使用不到索引的.

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JtWzkEJk-1688780333048)(.\img\40.jpg)]

3. 不要在索引列上做任何计算

不要在索引列上做任何操作,比如计算、使用函数、自动或手动进行类型转换,会导致索引失效,从而使查询转向全表扫描。

  • 插入数据

    xxxxxxxxxx
    
    INSERT INTO users(user_name,user_age,user_level,reg_time) VALUES('11223344',22,'D',NOW());
    
  • 场景1: 使用系统函数 left()函数

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE LEFT(user_name, 6) = '112233';
    

    ​ where条件使用计算后的索引字段 user_name,没有使用索引,索引失效。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rKkyEog1-1688780333048)(.\img\10.jpg)]

  • 场景2: 字符串不加单引号 (隐式类型转换)

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_name = 11223344;
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yUIxLJ38-1688780333049)(.\img\724444.jpg)]

注: Extra = Using where 表示Mysql将对storage engine提取的结果进行过滤,过滤条件字段无索引;

( 需要回表去查询所需的数据 )

4. 范围之后全失效

存储引擎不能使用索引中范围条件右边的列

  • 场景1: 条件单独使用user_name时, type=ref, key_len=82

    xxxxxxxxxx
    
    -- 条件只有一个 user_name
    
    EXPLAIN SELECT * FROM users WHERE user_name = 'tom';
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lX7o3jjZ-1688780333049)(.\img\11.jpg)]

  • 场景2: 条件增加一个 user_age ( 使用常量等值) ,type= ref , key_len = 86

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_name = 'tom' AND user_age = 17;
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c4GzImnZ-1688780333049)(.\img\12.jpg)]

  • 场景3: 使用全值匹配, type = ref , key_len = 168 , 索引都利用上了.

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_name = 'tom' 
    
    AND user_age = 17 AND user_level = 'A';
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XbMFpZzd-1688780333050)(.\img\13.jpg)]

  • 场景4: 使用范围条件时, avg > 17 , type = range , key_len = 86 , 与场景3 比较,可以发现 user_level 索引没有用上.

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_name = 'tom' 
    
    AND user_age > 17 AND user_level = 'A';
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mQRWgWE7-1688780333050)(.\img\14.jpg)]

5. 尽量使用覆盖索引

尽量使用覆盖索引(查询列和索引列尽量一致,通俗说就是对A、B列创建了索引,然后查询中也使用A、B列),减少select *的使用。

  • 场景1: 全值匹配查询, 使用 select *

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_name = 'tom' AND user_age = 17 
    
    AND user_level = 'A';
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aGRzWYP8-1688780333050)(.\img\15.jpg)]

  • 场景1: 全值匹配查询, 使用 select 字段名1 ,字段名2

    xxxxxxxxxx
    
    EXPLAIN SELECT user_name , user_age , user_level FROM users WHERE user_name = 'tom' 
    
    AND user_age = 17 AND user_level = 'A';
    

    使用覆盖索引(查询列与条件列对应),可看到Extra从Null变成了Using index,提高检索效率。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dLEoWZXb-1688780333051)(.\img\16.jpg)]

注: Using index 表示 使用到了索引 , 并且所取的数据完全在索引中就能拿到,

(使用覆盖索引的时候就会出现)

6. 使用不等于(!=或<>)会使索引失效

使用 != 会使type=ALL,key=Null,导致全表扫描,并且索引失效。

  • 使用 !=

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_name != 'tom';
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xfdbKRdk-1688780333051)(.\img\17.jpg)]

7. is null 或 is not null也无法使用索引

在使用is null的时候,索引完全失效,使用is not null的时候,type=ALL全表扫描,key=Null索引失效。

  • 场景1: 使用 is null

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_name IS NULL;
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SFCRT8xA-1688780333052)(.\img\18.jpg)]

  • 场景2: 使用 not null

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_name IS NOT NULL;
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ectYGPOL-1688780333052)(.\img\19.jpg)]

8. like通配符以%开头会使索引失效

like查询为范围查询,%出现在左边,则索引失效。%出现在右边索引未失效。口诀:like百分加右边。

  • 场景1

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_name LIKE '%tom%';
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7IcPJBim-1688780333052)(.\img\20.jpg)]

  • 场景2

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_name LIKE '%tom';
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Dl4PQGs-1688780333053)(.\img\21.jpg)]

  • 场景3

    xxxxxxxxxx
    
    EXPLAIN SELECT * FROM users WHERE user_name LIKE 'tom%';
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l8GJuXWz-1688780333053)(.\img\22.jpg)]

注: Using index condition 表示 查找使用了索引,但是需要;';查询数据

解决%出现在左边索引失效的方法:使用覆盖索引。

Case1:

xxxxxxxxxx
EXPLAIN SELECT user_name FROM users WHERE user_name LIKE '%jack%';

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0gR1yhok-1688780333054)(.\img\23.jpg)]

  • 对比场景1可以知道, 通过使用覆盖索引 type = index,并且使用了 Using index,从全表扫描变成了全索引扫描.

注: Useing where; Using index; 查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据

Case2:

xxxxxxxxxx
EXPLAIN SELECT id FROM users WHERE user_name LIKE '%jack%';

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wnQHiZ83-1688780333054)(.\img\24.jpg)]

  • 这里出现 type=index因为主键自动创建唯一索引。

Case3:

xxxxxxxxxx
EXPLAIN SELECT user_name,user_age FROM users WHERE user_name LIKE '%jack%';
EXPLAIN SELECT user_name,user_age,user_level FROM users WHERE user_name LIKE '%jack%';
EXPLAIN SELECT id,user_name,user_age,user_level FROM users WHERE user_name LIKE '%jack%';

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mu0tyc6F-1688780333055)(.\img\21114.jpg)]

  • 上面三组, explain执行的结果都相同,表明都使用了索引.

Case4:

xxxxxxxxxx
EXPLAIN SELECT id,user_name,user_age,user_level,reg_time FROM users WHERE user_name 
LIKE '%jack%';

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wye4Cwff-1688780333055)(.\img\25.jpg)]

  • 分析:由于只在(user_name,user_age,user_level)上创建索引, 当包含reg_time时,导致结果集偏大(reg_time未建索引)【锅大,锅盖小,不能匹配】,所以type=ALL。

  • like 失效的原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lp6qrEsY-1688780333056)(.\img\411110.jpg)]

  1. %号在右: 由于B+树的索引顺序,是按照首字母的大小进行排序,%号在右的匹配又是匹配首字母。所以可以在B+树上进行有序的查找,查找首字母符合要求的数据。所以有些时候可以用到索引.
  2. %号在左: 是匹配字符串尾部的数据,我们上面说了排序规则,尾部的字母是没有顺序的,所以不能按照索引顺序查询,就用不到索引.
  3. 两个%%号: 这个是查询任意位置的字母满足条件即可,只有首字母是进行索引排序的,其他位置的字母都是相对无序的,所以查找任意位置的字母是用不上索引的.

9. 字符串不加单引号导致索引失效

varchar类型的字段,在查询的时候不加单引号导致索引失效,转向全表扫描。

  • 场景1

    xxxxxxxxxx
    
    SELECT * FROM users WHERE user_name = '123';
    
    SELECT * FROM users WHERE user_name = 123;
    

    上述两条sql语句都能查询出相同的数据。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-72WuMtD3-1688780333056)(.\img\26.jpg)]

  • 场景2:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RJJJEOBa-1688780333056)(.\img\27.jpg)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DfJZmhRT-1688780333057)(.\img\28.jpg)]

    通过explain执行结果可以看出,字符串(name)不加单引号在查询的时候,导致索引失效(type=ref变成了type=ALL,并且key=Null),并全表扫描。

10. 少用or,用or连接会使索引失效

在使用or连接的时候 type=ALL,key=Null,索引失效,并全表扫描。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q0nH03HK-1688780333057)(.\img\29.jpg)]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/730603.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

程序员的悲哀是什么?

点击下方“JavaEdge”&#xff0c;选择“设为星标” 第一时间关注技术干货&#xff01; 免责声明~ 切记&#xff0c;任何文章不要过度深思&#xff08;任何东西都无法经得起审视&#xff0c;因为这世上没有同样的成长环境&#xff0c;也没有同样的认知水平同时也「没有适用于所…

大模型高效训练基础知识:梯度累积(Gradient Accumulationn)

梯度累积 梯度累积&#xff08;Gradient Accumulation&#xff09;的基本思想是将一次性的整批参数更新的梯度计算变为以一小步一小步的方式进行&#xff08;如下图&#xff09;&#xff0c;具体而言该方法以小批次的方式进行模型前向传播和反向传播&#xff0c;过程中迭代计算…

变革管理中的几个不错的模型小结

其他的变革模型&#xff1a; 变革管理流程&#xff1a;

二、Java的变量

二、变量 2.1、关键字与保留字 关键字 定义&#xff1a;赋予特殊含义&#xff0c;用做专门用途的字符串 特点&#xff1a;关键字的所有字母都为小写 保留字&#xff08;reserved word&#xff09; 现有Java版本尚未使用&#xff0c;但以后版本可能会作为关键字使用。自己命名…

使用PYQT制作人才交流管理系统

利用使用PYQT制作一个人才交流管理系统&#xff0c;先使用QT designer.exe设计好人才交流管理系统的各个UI界面&#xff0c;然后利用pyuic把生成的ui界面编译为py文件&#xff0c;在主函数文件内创建一个类继承ui.py界面的类&#xff0c;即可完成数据库逻辑与 GUI 代码分离&…

小米不再忍耐,裁员三分之一强势反击印度,印度制造或因此梦破

就在小米公司表态继续投资印度之后不久&#xff0c;印度媒体报道指小米印度公司的员工数量从1500人减少到1000人左右&#xff0c;这显示出小米开始强势反击印度&#xff0c;业界人士指出此举的影响远不止于此&#xff0c;结果很可能是导致印度制造的梦想破灭。 1.小米为印度手机…

软件工程——第9章面向对象方法学引论知识点整理

本专栏是博主个人笔记&#xff0c;主要目的是利用碎片化的时间来记忆软工知识点&#xff0c;特此声明&#xff01; 文章目录 1.当前最好的软件开发技术是&#xff1f; 2.面向对象的原则是什么&#xff1f; 3.人们把客观世界中的实体抽象为什么&#xff1f; 4.软件系统本质上…

主诉病程时长提取

编写Python函数 import re def structured_pro(original_text,keyword,out_unitNone):pattern_split_str[。&#xff0c;]pattern_splitre.compile(pattern_split_str,re.I|re.M)original_listpattern_split.split(original_text)pattern_keywordre.compile(keyword,re.I|re.M…

目前最好的MicrosoftProject替代方案

Microsoft Project是一个功能强大的项目管理工具。然而它可能是昂贵的&#xff0c;并且可能不适合所有的项目管理需求。幸运的是&#xff0c;有几个Microsoft Project的替代方案提供了类似的特性和功能。在本文中我们将探索目前可用的一些最好的Microsoft Project替代方案。 1、…

12.4 ARM异常处理

目录 ARM异常处理&#xff08;一&#xff09; 异常 概念 异常处理机制 ARM异常源 概念 ARM异常源 ARM异常模式 ARM异常处理&#xff08;二&#xff09; ARM异常响应 异常向量表 异常返回 IRQ异常举例​编辑 ARM异常处理&#xff08;三 &#xff09; 异常优先级 …

自我介绍这样写?

已经帮小伙伴改了 500 多份简历了&#xff0c;也发现了一些大家写简历时的共性问题。其中让我印象比较深刻的一个点就是 自我介绍 &#xff0c;基本上所有同学的自我介绍都是这么写的&#xff1a; 读这篇文章的朋友们&#xff0c;你是不是也是这么写自我介绍的呢&#xff1f; 这…

MySQL索引优化整合案例实现

目录 1 JOIN优化1.1 JOIN算法原理1.2 in和exists函数 2 order by优化2.1 索引排序2.2 额外排序2.3 排序优化 3 索引单表优化案例3.1. 建表3.2. 单表索引分析3.1.1 需求3.1.2 优化 4 索引多表优化案例 1 JOIN优化 1.1 JOIN算法原理 1) JOIN回顾 JOIN 是 MySQL 用来进行联表操作…

在 Jetpack Compose 中创建 BottomAppBar

Jetpack Compose 是 Android 的现代 UI 工具包&#xff0c;它使得构建美观且功能强大的应用变得更加简单。在本文中&#xff0c;我们将探讨如何使用 Jetpack Compose 创建一个 BottomAppBar。 开始之前 确保你的开发环境已经设置好了 Jetpack Compose。你需要使用 Android Stu…

矩阵Matrices

目录 矩阵的变换 向量和矩阵 矩阵的变换 房子图形的矩阵变换&#xff08;wiggle动态变换&#xff09; uicontrol的‘style’类型&#xff1a; X house dot2dot(X) theta1 wiggle(X) function dot2dot(X) % DOT2DOT Connect the points from a 2-by-n matrix. X(:,end1) X…

5 类数据,洞察游戏的秘密

数据犹如一扇扇窗户&#xff0c;透过它&#xff0c;我们可以洞察到游戏世界内部的诸多秘密。这些秘密&#xff0c;就像是隐藏在房间深处的宝藏&#xff0c;只有真正理解并善用它们&#xff0c;我们才能创造出更吸引人的游戏&#xff0c;形成更成功的商业模式。 一个关键的问题是…

【Linux】—— 浅谈进程优先级

本期&#xff0c;我们将来聊聊的是关于进程优先级的相关知识&#xff01;&#xff01;&#xff01; 目录 序言 &#xff08;一&#xff09;基本概念 &#xff08;二&#xff09;查看系统进程 1、PRI and NI 2、PRI vs NI &#xff08;三&#xff09;设置优先级 序言 首先…

关于antdesign-vue的layout组件样式失效问题(#components-layout-demo-custom-trigger)

1.错误描述 使用antdesign vue 中的layout作为主要布局&#xff0c;https://www.antdv.com/components/layout-cn 正常引入后&#xff0c;跟期望的样子不一样 期望中的样子 实际的样子 logo没有了&#xff0c;而且此时也无法更改样式。 此时的样式是这样的 无论怎么修改都…

Grafana 使用Rest API 作为数据源的实践

本文使用最新版本的Grafana 10 进行操作。 如果要使用Rest API 作为grafana 的数据源&#xff0c;可以选择安装一个Infinity的数据源插件。 如果创建数据源时&#xff0c;搜不到infinity&#xff0c;点击find more 查找安装该数据源插件 1. 安装 Infinity 数据源插件&#xf…

IP 协议的相关特性

目录 IP协议有三大特点&#xff1a;无连接、无状态、不可靠。 四位版本号 四位头部长度 八位服务类型: 十六位总长度 16 位标识, 3 位标志, 13 位片偏移 八位生存时间 八位协议 十六位首部校验和 关于IP v4地址不够的问题 ip地址动态分配: ip地址转换(NAT) 数据传输…

一个空的Object在内存中占用几个字节

文章目录 一、对象在内存中的布局1. 对象头1.1. 哈希码&#xff08;Hash Code&#xff09;&#xff1a;1.2. 对象所属的年代&#xff08;Generation&#xff09;&#xff1a;1.3. 对象锁&#xff08;Object Lock&#xff09;&#xff1a;1.4. 锁状态标志&#xff08;Lock State…