mysql 大于号 优化_SQL优化 MySQL版 - 避免索引失效原则(二)

避免索引失效原则(二)

注:继上一篇文章继续讲解:

避免索引失效原则(一)https://www.cnblogs.com/StanleyBlogs/p/10482048.html#4195062

作者 : Stanley 罗昊

【转载请注明出处和署名,谢谢!】

体验SQL优化中的概率情况

在上一篇文章结尾处,我们在执行查询计划的时候,却发现我明明加了索引,并且也满足了使用索引的条件,但是,给我的优化结果却是失败,从而,得出一个结论便是,优化是概率的,也就跟彩票一样,不可能百分之百优化成功的,但是彩票我们都知道,全凭运气,但是这里就不一样了,我们需要了解SQL优化概率背后到底是谁导致它优化失败的;

首先,我们来了解下,出现概率优化的原因:因为在SQL底层中,有一个服务层,服务层有一个SQL优化器,当我们写一条语句,虽然我们手动优化了,但是,优化器觉得你优化的不太合适,它可能会进行一些自己的干扰,干扰完毕之后就执行结果就不再是你理想中的那样了,所以这个优化器有的时候会阻扰我们的优化工作;

接下来,我们就通过几个例子来体验一下我们设想的优化和实际不一样的一些操作;

首先,我们需要建立一个复合索引:

alter table book add index idx_book_at(authorid,typeid);

建立完索引后,我们进行一个简单的查询:

explain select * from book where authorid = 1 and typeid = 2;

22aed8d8b15d6ae206269a156653531d.png

通过结果我们可以发现,复合索引全部生效了;

那么接下来,我们将体验一下让它产生概率问题,我把上面的SQL语句拿过来改改:

explain select * from book where authorid > 1 and typeid = 2;

我们查看执行结果:

9ae1481ed5e31977c97a13f617703471.png

结果很明显,给authorid 添加了一个大于号,这样则导致了右侧索引全部失效,包括自身,从而得出一个结论,复合索引中如果有>,则自身已经后面的索引都将会失效;

但是,这次我SQL语句再次改变,奇怪的事情将会发生:

explain select * from book where authorid = 1 and typeid > 2;

这次我把这个大于号加给了typeid字段,显然它也是索引,刚才我说了,添加大于号会导致自身并且右侧索引全部失效,但是接下来:

d267830ad01e3c22014fce21129f23be.png

现在我们又发现,结论又不对了,我明明自身肯定失效啊,为啥这次偏偏却两个都生效了?

原因就是概率情况,咱们在实际执行时,复合索引全部使用了,并不是刚才我们说的那个结论,自身失效及右侧全部失效,当然,这个情况是大部分情况下都是有用了,仅有小部分情况会出现;

明显的概率问题

刚才我写了几个例子看起来不是特别的明显,下面我将写几个比较明显的例子来体验一下概率问题;

首先,我们编写一条SQL语句:

explain select * from book where authorid < 1 and typeid = 2;

此时,我把authorid改成了小于号,我们看结果:

e3a2e232ebe1720e0eb475e08a1f005b.png

我们看到了,此时,我们换层了小于号,发现没有全部失效,此条语句得出结论,两个索引,仅生效了一个因为范围查询仅对自身生效,对后面的不会生效;

接下来,我再改变一下SQL语句:

explain select * from book where authorid < 4 and typeid = 2;

首先看清楚,我现在没有更改任何符号,仅把authorid小于号后面的数字条件写成了4,再来看看执行结果:

f322077f9d5255fe1518ce7714f08455.png

我们惊奇的发现,竟然全部失效了,我明明就光改了一个数字而已,就全部失效了,刚才还有一个生效,现在一个都没有了,这到底是为什么呢?

通过后两个例子我们发现,就改了一个数,索引都不一样了,所以,这就是SQL优化的一个概率;

因此得出结论,我们学习的索引优化,是一个大部分情况都适用的结论,但由于SQL优化器等原因,该结论不是100%正确,因为SQL的底层把我们写的语句给干扰了;

一般而言,范围查询(> < in),之后的索引失效,仅对自身生效;

补救

那么,如果这样一直干扰下去,我们到底还优不优化了?就没有办法来补救这个概率问题吗?答案是有的;

尽量使用索引覆盖 (using index)在Extra里面出现这个,就表示你的SQL语句不会出错,如果你怕在优化中出现概率问题,那么你就朝着using index这个方向去优化,因为,出现这个就代表你这条SQL100%生效,不会出现概率问题;

比如我现在有 a b c三张表;

现在我编写一条SQL,select a,b,c from 表名 where a = ... and b = ...;

在select后面我们用到了abc 并且查询条件也是a b 没有跨列,满足最佳做前缀,最主要的是查询条件也是索引,所有的索引你都按照规则全部用上了,这样就会出现索引覆盖,大大的提高了系统性能;

like尽量以“常量”开头,不要以'%'开头,否则索引失效

我现在编写一条SQL语句;

select * from 表名 where name like '%x%';

首先,这条sql语句是查询表名中name 带有x的数据,如果你这样写了,如果name是索引,那么name将会失效!

接下来,我结合数据库进行证实一下;

explain select tname from teacher where tname like '%x%'

首先,tname我是加了一个索引的,但是看一下看一下执行结果:

bc2fda6e5a948a81d2b13e3ccb945a8a.png

没有失效,因为出现了覆盖索引,因为tname是索引,我刚好去查tname,所以出现了覆盖索引,导致本次查询没有失效,下面我把它换成“*”;

值得注意的是,在开发过程中,严禁出现“*”!本次为了说明问题,所以换成“*”;

执行结果:

21803aeb52c3799795aa23b927a6b2d1.png

索引全部失效!原因我刚才也说过了,在模糊查询是,不要以百分号开头;

如果想避免失效,可以变成以下这种写法:

explain select tname from teacher where tname like 'x%'

这样虽然可以保证索引不会失效,但是,我们在项目开发中,难免遇到模糊查询,所以也是有解决方案的;

刚才我不小心也试出来了,因为我使用了索引覆盖,你想用模糊查询可以,但是你需要有索引覆盖,刚才我查询tname,tname本身就在索引里面,所以出现了索引覆盖;

如果必须使用模糊查询,那么就把查询条件以及需要查询的字段全部声明成索引即可;

尽量不要使用类型转换(显示、隐式),否则索引失效

这里我就简单的举个例子:

select * from teacher where tname = 'abc';

此时,tname是varchar类型,这个时候你你却写成int类型:

select * from teacher where tname = 123;

人家本来需要单引号的字符串类型,结果你给人家弄了一个去掉引号的int类型,所以索引就会失效;

尽量不要使用or,否则索引失效

select * from teacher where tname = " " or tcid>1;

这条sql语句就会导致索失效,所以要避免使用or这个关键字!

经过测试发现,or回导致以左的索引失效,也就是tname这个字段的索引失效了;

今日感悟:

努力就一定会有收获,心无旁骛

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

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

相关文章

mysql 唯一索引 死锁_MySQL 死锁套路:唯一索引 S 锁与 X 锁的爱恨情仇

毫不夸张的说&#xff0c;有一半以上的死锁问题由唯一索引贡献&#xff0c;后面介绍的很多死锁的问题都跟唯一索引有关。这次我们讲一段唯一索引 S 锁与 X 锁的爱恨情仇我们来看一个简化过的例子# 构造数据CREATE TABLE t1 (id int(11) NOT NULL AUTO_INCREMENT,name varchar(1…

ejb 示例 2018_EJB钝化和激活示例

ejb 示例 2018在本教程中&#xff0c;我们将了解状态Java企业会话Bean中激活和钝化的工作方式。 1.简介 有状态会话Bean通常保存有关特定客户端的信息&#xff0c;并在整个会话中保存该信息。 但是&#xff0c;事实是&#xff0c;客户端会话往往会在相当长的时间内保持活动状态…

js微信小程序页面左上角返回跳转指定页面

微信小程序非导航栏tabBar页面左上角返回默认返回上一次的页面&#xff08;即进入当前页面的前一页面&#xff09;&#xff0c;如果需要自定义页面&#xff0c;可以通过js中onUnload函数进行指定页面跳转。 ①关闭所有页&#xff0c;打开url指定页面 onUnload: function () {…

服务器mysql显示链接次数太多,服务器mysql显示链接次数太多

服务器mysql显示链接次数太多 内容精选换一换在本章节中&#xff0c;您将会把游戏应用部署到CCE云容器引擎中&#xff0c;您需要执行以下操作&#xff1a;创建集群&#xff1a;集群是运行应用的逻辑分组&#xff0c;包含一组云服务器资源&#xff0c;每个节点对应一台云服务器。…

使用JUnit 5在Mockito中方便地进行模拟–官方方式

从版本2.17.0开始&#xff0c;如果使用JUnit 5&#xff0c; Mockito提供了官方&#xff08;内置&#xff09;支持来管理模拟生命周期。 入门 为了利用该集成&#xff0c;需要在JUnit 5的junit-platform-engine旁边添加Mockito的mockito-junit-jupiter依赖项&#xff08;有关详…

esp32搭建文件服务器,ESP32入门示例 - SD卡Web服务器

这个是来自ESP32官方示例的改版&#xff0c;官方的示例由于存在一些问题所以我进行了修改原本的示例有点逻辑上的问题&#xff0c;所以进行了一些修改主要修改有&#xff1a;1.新增SD卡测试部分 复制自官方SD卡示例2.新增一个根目录页&#xff0c;访问根目录就可以看到3.修改了…

mysql 配置文件在哪_MySQL+MyCat分库分表 读写分离配置

一、 MySQLMyCat分库分表1 MyCat简介java编写的数据库中间件Mycat运行环境需要JDK。Mycat是中间件&#xff0c;运行在代码应用和MySQL数据库之间的应用。前身&#xff1a; corba&#xff0c;是阿里开发的数据库中间件&#xff0c;实现MySQL数据库分库分表集群管理的中间件&…

字符串String截取字符char

字符串类的charAt() 方法可返回指定位置的字符。 stringObject.charAt(index)从键盘输入获取了一个字符串&#xff0c;将其数据类型转换为字符型。 Scanner scan new Scanner(System.in); String str scan.next(); char ca str.charAt(0);示例&#xff1a; import java.u…

Java基本语法(14)--for循环结构

循环结构&#xff1a;在某些条件满足的情况下&#xff0c;反复执行特定代码的功能。 基本格式&#xff1a; for (①初始化部分; ②循环条件部分; ④迭代部分)&#xff5b; ③循环体部分; &#xff5d;如果①&#xff0c;④部分多条语句&#xff0c;语句之间用“&#xff0c;”…

Java 8中的功能接口是什么? @功能注释和示例

函数接口是Java 8最重要的概念之一&#xff0c;实际上为lambda表达式提供了动力&#xff0c;但是许多开发人员没有首先了解函数接口在Java 8中的作用就花了很多精力来理解它&#xff0c;并花时间学习lambda表达式和Stream API。除非您知道什么是功能接口以及lambda与它之间的关…

win10存储池_3个光威480G SSD组WIN10存储池,深度测试到底值不值得搞

上次由于我SSD不够&#xff0c;所以我用虚拟硬盘的方式&#xff0c;虚拟了3个VHDX硬盘&#xff0c;组了个奇偶校验的存储池&#xff0c;并且简单的做了测试。测试结果是&#xff0c;组存储池确实提高了我们的数据安全性。WIN10存储池&#xff0c;可以让我们玩家省去组RAID&…

截止角频率和截止频率的关系_开关电源的控制环截止频率和开关频率有什么关系?...

【新朋友】点击上方蓝字“电源之家”关注【老朋友】点击右上角按钮&#xff0c;分享到朋友圈电源之家官方技术③群&#xff1a;522815202(3000人群)(电源行业第一大技术交流QQ群)这个问题很专业&#xff0c;因此答案注定也专业而非科普&#xff0c;非电力电子专业小伙伴看不懂很…

restlet_Restlet框架– Hello World示例

restletRestlet是用于Java平台的轻量级&#xff0c;全面的开源REST框架。 Restlet适用于服务器和客户端Web应用程序。 它支持主要的Internet传输&#xff0c;数据格式和服务描述标准&#xff0c;例如HTTP和HTTPS&#xff0c;SMTP&#xff0c;XML&#xff0c;JSON&#xff0c;At…

在运行时在Spring Cloud Config中刷新属性配置

在本系列Spring Cloud Config的教程系列中&#xff0c;我们将讨论在运行时刷新属性配置的过程&#xff0c;我们将使用Spring Boot致动器/refresh端点进行/refresh 。 此外&#xff0c;我们还将研究使用RefreshScope注释刷新Value属性。 在我的Spring Cloud Config的上一教程中…

pythonnumpy教程_Python学习教程:通俗易懂的Numpy入门教程

Numpy是python语言中最基础和最强大的科学计算和数据处理的工具包&#xff0c;如数据分析工具pandas也是基于numpy构建的&#xff0c;机器学习包scikit-learn也大量使用了numpy方法。本文介绍了Numpy的n维数组在数据处理和分析的所有核心应用。目录如何构建numpy数组如何观察数…

css hack技巧_5种减少Hack的编码技巧

css hack技巧在本文中&#xff0c;我们将探讨五种方法&#xff0c;这些方法可以使用有效的编码来帮助垃圾回收器花费更少的CPU时间分配和释放内存&#xff0c;并减少GC开销。 较长的GC通常会导致我们的代码在回收内存时停止&#xff08;也称为“停止世界”&#xff09;。 一些…

mysql数据库全备_MySQL innobackupex全备是指什么

MySQL innobackupex全备是指什么发布时间&#xff1a;2020-06-03 10:10:31来源&#xff1a;51CTO阅读&#xff1a;133作者&#xff1a;三月下文主要给大家带来MySQL innobackupex全备是指什么&#xff0c;希望这些内容能够带给大家实际用处&#xff0c;这也是我编辑MySQL innob…

数组初始化使用(写)new与不使用(不写)new

首先&#xff0c;数组初始化时&#xff0c;写不写new没有区别的。int arr[] new int[]{ 3, 9, 8};或者int[] arr {3,9,8};编译器遇到 int a[] {3, 8, 9}; 会编译成和 int a[] new int[] {3, 8, 9}; 完全一样的中间代码。 ①不同于String类。String由于实现了常量池&#xf…

Java数组(2)--一维数组

一、一维数组的&#xff08;声明赋值&#xff09;初始化 声明&#xff1a;type var[]; 或 type[] var;&#xff08;示例&#xff1a;int[] age;&#xff09; 初始化&#xff1a; ①动态初始化&#xff1a;声明且为数组元素分配空间&#xff0c;与赋值的操作分开进行 int[] ar…

Java数组(3)--二维(多维)数组

二维数组相当于一维数组的元素是一维数组 一、二维数组声明赋值初始化 动态初始化① int[][] arr new int[3][2];定义了名称为arr的二维数组 二维数组中有3个一维数组 每一个一维数组中有2个元素 一维数组的名称分别为arr[0], arr[1], arr[2] 给第一个一维数组1脚标位赋值为…