MySQL索引的使用,大大提升你代码的效率

news2024/11/16 5:53:57

目录

🚀索引使用

🚀最左前缀法则

 🚀范围查询

 🚀索引失效情况

隐式类型转换是什么?

隐式类型转换的影响

举例说明

无隐式类型转换的情况

存在隐式类型转换的情况

总结

🚀模糊查询

🚀or连接条件

🚀数据分布影响


🚀索引使用

验证索引效率

案例:这是一张有1000w的记录的表 (此案例来自黑马,我觉得黑马的案例很详细)

这张表中id为主键有主键索引而其他字段是没有建立索引的先来查询其中的一条记录看里面的字段情况,执行如下SQL

select * from tb_sku where id = 1\G;

 可以看到即使有1000w的数据,根据id进行数据查询,性能依然很快0.00sec为主键id是有索引的

下来,我们再来根据 sn字段进行查询执行如下SQL

SELECT * FROM  tb_sku  WHERE sn = '100000003145001 ';

我们可以看到根据sn字段进行查询查询返回了一条数据结果耗时  20.78sec就是因为sn没有索 引,而造成查询效率很低。

具体原因:首先,它没有使用索引。在没有索引的情况下,MySQL将扫描整个表来查找符合条件的行。这可能会导致性能下降,尤其是当表中的数据量很大时。

 我们可以针对于sn字段建立一个索引建立了索引之后我们再次根据sn进行查询再来看一 下查询耗时情况。

create  index  idx_sku_sn  on  tb_sku (sn) ;

然后再次执行相同的SQL语句再次查看SQL的耗时 

SELECT * FROM  tb_sku  WHERE sn = '100000003145001 ';

由此可以看出,建立了索引之后,查询的性能极大提升,因为MySQL可以使用索引来快速定位匹配的行,并进一步筛选符合额外条件的行。这将大大提高查询的效率,因为MySQL只需要访问少量的行来获取结果。

需要注意的是,索引并非在所有情况下都能提高查询性能。索引的选择和使用需要根据具体的数据和查询需求进行评估。过多或不必要的索引可能会增加写操作的开销,而且索引也需要占用额外的存储空间。因此,在设计和使用索引时,需要综合考虑查询频率、数据更新频率和存储成本等因素。

🚀最左前缀法则

show index from tb_user ; --显示tb_user表的索引

如果索引了多列(联合索引要遵守最左前缀法则最左前缀法则指的是查询从索引的最左列开始 并且不跳过索引中的列。如果跳跃某一列,索引将会部分失效(即面的字段索引失效)

 这些标记出来的是单链索引,主键id,phone,name,email

在  tb_user 表中有一个联合索引这个联合索引涉及到三个字段顺序分别为  profession age  status

对于最左前缀法则指的是查询时最左变的列也就是profession必须存在否则索引全部失效 而且中间不能跳过某一列,否则该列后面的字段索引将失效.

演示:

explain select * from tb_user where profession = '化工 ' and age = 38 and status
= '5 ';

 explain select * from tb_user where profession = '化工 ' and age = 38;

explain select * from tb_user where profession = '化工 ';    

 以上的这三组测试中,我们发现只要联合索引最左边的字段  profession索引就会生效只不 过索引的长度不同。    而且由以上三组测试,我们也可以推测出profession字段索引长度为47  age 字段索引长度为2  status字段索引长度为5

explain select * from tb_user where age = 38 and status = '5 ';

explain select * from tb_user where status = '5 ';

 而通过上面的这两组测试,我们也可以看到索引并未生效,原因是因为不满足最左前缀法则,联合索引 最左边的列profession不存在。

explain select * from tb_user where profession = '化工 ' and status = '5 ';

 上述的SQL查询时,存在profession字段,最左边的列是存在的,索引满足最左前缀法则的基本条   件。但是查询时,跳过了age这个列,所以后面的列索引是不会使用的,也就是索引部分生效,所以索 引的长度就是47。

 思考题:

当执行SQL语句 :

 explain select * from tb_user where age = 38 and   status = '0' and profession = '化工 '; 

是否满足最左前缀法则,走不走上述的联合索引,索引长度是多少?(也就是顺序换了之后还成不成立了)

可以看到,是完全满足最左前缀法则的,索引长度54联合索引是生效的

注意  :最左前缀法则中指的最左边的列,是指在查询时,联合索引的最左边的字段(即是

第一个字段)必须存在,与我们编写SQL时,条件编写的先后顺序无关。

 🚀范围查询

联合索引中,出现范围查询 (>,<)范围查询右侧的列索引失效

explain select * from tb_user where profession = '化工 ' and age > 30 and status
= '5 ';

当范围查询使用>   < 走联合索引了,但是索引的长度为49就说明范围查询右边的status段是没有走索引的。

explain select * from tb_user where profession = '化工 ' and age >= 30 and
status = '5 ';

当范围查询使用>=   <= 时,走联合索引但是索引的长度为54就说明所有的字段都是走索引的。所以,在条件允许的情况下,尽可能的使用类似于  >=   <= 这类的范围查询而避免使用  >   <

 🚀索引失效情况

索引列运算

不要在索引列上进行运算操作,索引将失效

tb_user表中除了前面介绍的联合索引之外还有一个索引phone字段的单列索引

当根据phone字段进行等值匹配查询时, 索引生效

explain select * from tb_user where phone = '17799990015 ';

 当根据phone段进行函数运算操作之后索引失效

explain  select  *  from  tb_user  where  substring (phone,10,2) = '15 ';

 字符串不加引号

字符串类型字段使用时,不加引号,索引将失效。

示例:加单引号与不加单引号的区别

explain select * from tb_user where profession = '化工 ' and age = 38 and status
= '5 ';

explain select * from tb_user where profession = '化工 ' and age = 38 and status
= 5 ;

explain select * from tb_user where phone = '17799990015 ';
explain select * from tb_user where phone = 17799990015;

 经过上面两组示例我们会明显的发现如果字符串不加单引号对于查询结果没什么影响但是数 据库存在隐式类型转换,索引将失效。

隐式类型转换是什么?

隐式类型转换是指在比较操作中,MySQL会自动将一个数据类型转换成另一个数据类型,以便进行比较。这种转换是在不明确指定的情况下自动发生的,用户不需要显式地进行类型转换操作。

隐式类型转换的影响

隐式类型转换可能导致索引失效,从而影响查询性能。当查询条件中的数据类型与列的数据类型不匹配时,MySQL会进行隐式类型转换,将查询条件的数据类型转换成列的数据类型进行比较。如果数据类型不匹配,MySQL可能无法充分利用索引,而是需要进行全表扫描来查找符合条件的行,导致性能下降。

举例说明

无隐式类型转换的情况

假设我们有一个名为users的表,包含以下列:

+----+---------+--------+
| id | name    | age    |
+----+---------+--------+
| 1  | Alice   | 25     |
| 2  | Bob     | 30     |
| 3  | Charlie | 35     |
| 4  | David   | 40     |
| 5  | Eve     | 45     |
+----+---------+--------+

如果我们对name列创建了索引,并执行以下查询:

SELECT * FROM users WHERE name = 'Alice';

由于查询条件中的数据类型与列的数据类型完全匹配,MySQL可以充分利用索引来快速定位和访问符合条件的数据,从而提高查询效率。

存在隐式类型转换的情况

现在假设我们对age列创建了索引,并执行以下查询:

SELECT * FROM users WHERE age = 30;

在这个例子中,由于查询条件中的数据类型与列的数据类型完全匹配,MySQL可以充分利用索引。

但是,如果我们执行以下查询:

SELECT * FROM users WHERE age = '30';

在这个例子中,查询条件中的数据类型是字符串,而列的数据类型是整数。MySQL将会进行隐式类型转换,将字符串转换成整数进行比较。这可能导致索引失效,从而影响查询性能。

总结

隐式类型转换可能导致索引失效,影响查询性能。为了避免这种情况,我们应该尽量确保查询条件中的数据类型与列的数据类型完全匹配,以充分利用索引提高查询效率。

🚀模糊查询

如果仅仅是尾部模糊匹配索引不会失效如果是头部模糊匹配索引失效

接下来我们来看一下这三条SQL语句的执行效果查看一下其执行计划

由于下面查询语句中,都是根据profession字段查询,符合最左前缀法则联合索引是可以生效的 我们主要看一下,模糊查询时,%加在关键字之前,和加在关键字之后的影响。

explain  select  *  from  tb_user  where  profession like '金属% '; 
explain  select  *  from  tb_user  where  profession like '%材料  ';
explain  select  *  from  tb_user  where  profession like '%材% ';

经过上述的测试,我们发现,在like模糊查询中,在关键字后面加%,索引可以生效。而如果在关键字前面加了%,索引将会失效。

🚀or连接条件

or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索那么涉及的索引都不会被用到。

explain select * from tb_user where id = 6 or age = 33;
explain select * from tb_user where phone = '15377777775 ' or age = 27;

第二个指令输出的结果很明显,只有phone有索引,后面的age没有索引,所以涉及的索引都不会用到,age没有索引所以即使id  phone有索引索引也会失效所以需要针对于age也要建立索引

然后,我们可以对age字段建立索引

create index idx_user_age on tb_user (age);

 建立了索引之后我们再次执行上述的SQL语句看看前后执行计划的变化

 最终我们发现or连接的条件左右两侧字段都有索引时索引才会生效

🚀数据分布影响

如果MySQL评估使用索引比全表更慢则不使用索引

select * from tb_user where phone >= '17799990005 ';
select * from tb_user where phone >= '17799990015 ';

经过测试我们发现相同的SQL语句只是传入的字段值不同最终的执行计划也完全不一这是为什么呢?

就是因为MySQL在查询时,会评估使用索引的效率与走全表扫描的效率,如果走全表扫描更快,则放弃索引,走全表扫描。因为索引是用来索引少量数据的,如果通过索引查询返回大批量的数据,则还不如走全表扫描来的快,此时索引就会失效。

我们再来看看  is null   is not null 操作是否走索引

执行如下两条语句 

explain select * from tb_user where profession is null;
explain select * from tb_user where profession is not null;

接下来我们做一个操作将profession字段值全部更新为null

update tb_user set profession = null ;

 然后,再次执行上述的两SQL查看SQL语句的执行计划

最终我们看到一模一样的SQL语句先后执行了两次结果查询计划是不一样的为什么会出现这种现象,这是和数据库的数据分布有关系,查询时MySQL会评估走索引快还是全表扫描快果全表 扫描更快,则放弃索引走全表扫描. 因此, is null is not null是否走索引,得具体情况具体分析,并不是固定的


希望对大家有帮助! 

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

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

相关文章

经典面试题-死锁

目录 1.什么是死锁&#xff1f; 2.形成死锁的四个必要条件 3.死锁的三种情况 第一种情况&#xff1a; 举例&#xff1a; 举例&#xff1a; 第二种情况&#xff1a;两个线程 两把锁 举例&#xff1a; 第三种情况&#xff1a;N个线程 M把锁 哲学家进餐问题 1.什么是死锁&…

Docker基础语法

目录 一.docker安装 二.docker基础名词 三.docker基础命令 四.命令别名 五.数据卷 六.挂载本地目录或文件 七.Docker镜像 八.网络 一.docker安装 1.安装yum工具 yum install -y yum-utils device-mapper-persistent-data lvm2 2.安装 docker yum源 yum-config-manag…

Git的安装与配置

目录 前言 Linux-centos&#xff1a;下安装 Linux_ubuntu下安装 创建Git本地仓库 配置用户名和Email 前言 Git是一种版本控制器&#xff0c;能够让我们了解一个文件的历史&#xff0c;以及它的发展过程。通俗的将就是可以记录一个工程的每一次改动和版本迭代的一个管理系统…

书法AI全自动切字+识别算法2.0版发布,草书篆书行书楷书识别准确率超过90%,覆盖书法单字30万张

我们开发的业界识别最准覆盖作品最全的书法AI小程序上线了 书法AI全自动切字识别算法2.0版发布&#xff0c;草书篆书行书楷书识别准确率超过90%&#xff0c;准确率甩百度OCR一条街&#xff0c;覆盖书法单字30万张&#xff0c;遥遥领先同行 我们还可为客户提供书法AI全自动切字a…

Tensorflow2.0笔记 - tensor的合并和分割

主要记录concat,stack,unstack和split相关操作的作用 import tensorflow as tf import numpy as nptf.__version__#concat对某个维度进行连接 #假设下面的tensor0和tensor1分别表示4个班级35名同学的8门成绩和两个班级35个同学8门成绩 tensor0 tf.ones([4,35,8]) tensor1 tf…

C#,入门教程(30)——扎好程序的笼子,错误处理 try catch

上一篇&#xff1a; C#&#xff0c;入门教程(29)——修饰词静态&#xff08;static&#xff09;的用法详解https://blog.csdn.net/beijinghorn/article/details/124683349 程序员语录&#xff1a;凡程序必有错&#xff0c;凡有错未必改&#xff01; 程序出错的原因千千万&…

基于PSO-BP神经网络的风电功率预测(MATLAB)

作品简介 &#xff1a;关注公众号“电击小子程高兴的MATLAB小屋”获取优惠 主要内容 该模型将粒子群算法与BP神经网络结合用于BP神经网络的训练&#xff0c;即优化BP网络中的连接权值和各项阈值&#xff0c;然后利用神经网络分布式并行处理优势、自适应学习能力以及较好的…

坚持刷题 | 二叉树的最大深度

文章目录 题目考察点代码实现实现总结扩展用迭代的方式实现二叉树最大深度可能的扩展问题 坚持刷题&#xff0c;老年痴呆追不上我&#xff0c;今天刷&#xff1a;二叉树的最大深度 题目 104.二叉树的最大深度 考察点 二叉树的基本实现&#xff1a; 能够定义二叉树节点&…

Apifox接口测试教程(一)接口测试的原理与工具

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

性能优化-OpenCL 介绍

「发表于知乎专栏《移动端算法优化》」 本文首先对 GPU 进行了概述&#xff0c;然后着重地对移动端的 GPU 进行了分析&#xff0c;随后我们又详细地介绍了 OpenCL 的背景知识和 OpenCL 的四大编程模型。希望能帮助大家更好地进行移动端高性能代码的开发。 &#x1f3ac;个人简介…

git本地分支的合并/切换分支时遇到的问题

目录 第一章、本地分支的切换测试1.1&#xff09;切换之前的master分支下文件内容1.2&#xff09;切换到develop分支后修改文件1.3&#xff09;切回master分支出现报错&#xff1a; 第二章、解决方式2.1&#xff09;方式1&#xff1a;commit提交修改2.2&#xff09;方式2&#…

柔性数组和C语言内存划分

柔性数组和C语言内存划分 1. 柔性数组1.1 柔性数组的特点&#xff1a;1.2 柔性数组的使用1.3 柔性数组的优势 2. 总结C/C中程序内存区域划分 1. 柔性数组 也许你从来没有听说过柔性数组&#xff08;flexible array)这个概念&#xff0c;但是它确实是存在的。 C99 中&#xff…

解决Git添加.gitignore文件后不生效的问题

1. 问题描述 如上图所示&#xff0c;在已存在.gitignore文件且已经提交过的Git管理的项目中&#xff0c;其中.class、.jar文件以及.idea目录内的内容全部都还是被Git管理了&#xff0c;可见.gitignore文件并没有生效。 2. 原因发现 .gitignore文件只能作用于 Untracked Files…

vue+elementUI el-select 中 没有加clearable出现一个或者多个×清除图标问题

1、现象&#xff1a;下方截图多清除图标了 2、在全局common.scss文件中加一个下方的全局样式noClear 3、在多清除图标的组件上层div加noClear样式 4、清除图标去除成功

iOS应用程序混淆加固原理及逆向工具介绍

概要 本文将介绍iOS应用程序混淆加固的原理和常见的加固类型&#xff0c;以及介绍一些常用的逆向工具。同时还会介绍一种代码虚拟化技术&#xff0c;用于进一步保护应用程序不被逆向分析。 引言 移动应用程序开发面临着越来越严峻的安全挑战&#xff0c;特别是在越狱设备上…

k8s1.27.2版本二进制高可用集群部署

文章目录 环境软件版本服务器系统初始化设置关于etcd签名证书etcd集群部署负载均衡器组件安装设置关于k8s自签证书自签CAkube-apiserver 自签证书kube-controller-manager自签证书kube-scheduler自签证书kube-proxy 自签证书admin 自签证书 控制平面节点组件部署**部署kube-api…

Uni-App三甲医院、医保定点三甲医院在线预约挂号系统源码

医院在线预约挂号系统是一种方便患者预约挂号的系统&#xff0c;患者可以通过该系统进行预约挂号&#xff0c;省去了到医院现场排队等待的时间&#xff0c;提高了就诊效率。随着医院信息化水平的不断发展&#xff0c;医院在线预约挂号管理系统已成为医院管理中不可或缺的一部分…

如何在Linux部署JumpServer堡垒机并实现远程访问本地服务

文章目录 前言1. 安装Jump server2. 本地访问jump server3. 安装 cpolar内网穿透软件4. 配置Jump server公网访问地址5. 公网远程访问Jump server6. 固定Jump server公网地址 前言 JumpServer 是广受欢迎的开源堡垒机&#xff0c;是符合 4A 规范的专业运维安全审计系统。JumpS…

KAGGLE · GETTING STARTED CODE COMPETITION 图像风格迁移 示例代码阅读

本博文阅读的代码来自于I’m Something of a Painter Myself | Kaggle倾情推荐&#xff1a; Monet CycleGAN Tutorial | Kaggle 数据集说明 I’m Something of a Painter Myself | Kaggle Files monet_jpg - 300 Monet paintings sized 256x256 in JPEG formatmonet_tfrec -…

Redis相关面试题大全

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于java面试题系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基…