MySQL 优化 —— WHERE 子句优化

引言

本文翻译自 MySQL 官网:WHERE Clause Optimization

WHERE 子句优化

这一部分我们来讨论对 WHERE 子句的优化处理。本部分的案例都是以 SELECT 语句为例,但这些优化同样适用于 DELETE 和 UPDATE 语句中的 WHERE 子句。

注意

因为对 MySQL 优化器的工作一直在进行,因此并不是全部的MySQL执行优化都在本文档中说明。

你可能想重写你的查询以使它在算法操作上执行的更快,同时牺牲一定的可读性。但你通常可以不必这么费劲,因为MySQL 会自动进行类似的优化,同时保留查询的可读性和可维护性。下面一些是MySQL自己的优化:

  • 移除不必要的圆括号
   ((a AND b) AND c OR (((a AND b) AND (c AND d))))
-> (a AND b AND c) OR (a AND b AND c AND d)
  • 常量合并
   (a<b AND b=c) AND a=5
-> b>5 AND b=c AND a=5
  • 常量条件删除
   (b>=5 AND b=5) OR (b=6 AND 5=5) OR (b=7 AND 5=6)
-> b=5 OR b=6
  • 被索引使用的常量表达式只会计算一次
  • 单表的 COUNT(*) ,在没有 WHERE 子句的情况下可以直接从表信息中获得,但只针对 MyISAM 和 MEMORY 存储引擎。对于仅与一个表一起使用的任何NOT NULL表达式,也可以这样做。
  • 早期检测无效的常量表达式。MySQL 会快速地检测到一些根本不可能的 SELECT 语句,并直接返回空的结果集。
  • 如果你不使用 GROUP BY 或聚合函数(COUNT(),MIN()等),HAVING 子句会被合并到 WHERE 中。
  • 对于连接中的每张表,MySQL会构建更简单的 WHERE ,以此来获取每张表的快捷 WHERE 子句处理,同时尽可能快的跳过记录。
  • 所有的常量表会先于其他表的查询。下面所列都是常量表(其实博主认为这里应该翻译为“常量查询”更恰当一些):
  1. 空表或只有一条记录的表。
  2. 使用了 primary key 或者 unique key 作为 WHERE 查询条件的查询,并且条件都是等值判断,且所有索引列都是定义为非空的。(博主:因为主键、唯一键都可能是多列复合,所以这里要求每个索引列都必须的非空)。下面的表都被视为常量表:
SELECT * FROM t WHERE primary_key=1;
SELECT * FROM t1,t2WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
  • 通过尝试所有可能性,可以找到连接表的最佳连接组合。如果所有的 ORDER BY 和 GROUP BY子句中的字段都来自同一个表,那么这个表在连接时就作为第一张表。
  • 如果有一个 ORDER BY 子句和一个不同的 GROUP BY 子句,或者 ORDER BY 或 GROUP BY 包含的列不属于连接队列中的第一张表,那么MySQL就会建立一张临时表。
  • 如果你使用 SQL_SMALL_RESULT 修饰符,MySQL 会使用一张内存中的临时表。
  • 每张表的索引都会被查询,并会使用最优索引,除非MySQL优化器认为全表扫描比用索引更高效。曾经,扫描的使用基于是否最优索引覆盖超过了表数据的 30 % ,但是,固定的百分比不再作为使用索引或扫描的决定因素。如今的优化器更加复杂,它对优化的计算基于更多额外的因素,比如表的大小,记录的数量,以及 IO 块的大小。 
  • 有些情况,MySQL 甚至不需要访问数据文件就可以从索引中读取记录。如果索引中所有的列都是数值型的,那么只用索引树就可以完成查询。
  • 每条记录输出之前,那些不匹配 HAVING 子句条件的记录会被跳过。

下面一些查询例子都是非常快速的:

SELECT COUNT(*) FROM tbl_name;SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;SELECT MAX(key_part2) FROM tbl_nameWHERE key_part1=constant;SELECT ... FROM tbl_nameORDER BY key_part1,key_part2,... LIMIT 10;SELECT ... FROM tbl_nameORDER BY key_part1 DESC, key_part2 DESC, ... LIMIT 10;

下面的查询,MySQL只会用到索引树,假设创建了索引的列都是数值型的:

SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;SELECT COUNT(*) FROM tbl_nameWHERE key_part1=val1 AND key_part2=val2;SELECT key_part2 FROM tbl_name GROUP BY key_part1;

以下查询使用索引来检索排序的行,而不需要单独的排序传递:

SELECT ... FROM tbl_nameORDER BY key_part1,key_part2,... ;SELECT ... FROM tbl_nameORDER BY key_part1 DESC, key_part2 DESC, ... ;

总结

从本文可以看出,MySQL官方给出了一些 MySQL 优化器内部对于查询的优化处理,对于开发者的优化建议虽然没有明确指出,但是我们可以通过分析这些来自优化器内部的操作来定制我们的SQL查询。这些知识可以作为我们日后采取更具体优化措施的原理基础。

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

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

相关文章

MySQL 优化 —— IS NULL 优化

引言 本博客翻译自 MySQL 官网&#xff1a;IS NULL Optimization&#xff0c; MySQL版本 5.7。 MySQL 对 IS NULL 的优化 MySQL 可以对 IS NULL 执行和常量等值判断&#xff08;列名 常量表达式&#xff0c;如name Tom&#xff09;相同的优化。MySQL 可以利用索引和范围来…

MySQL 优化 —— ORDER BY 优化

引言 本文翻译自MySQL 官网&#xff1a;ORDER BY Optimization&#xff0c;MySQL 版本&#xff1a;5.7。 这一部分描述了MySQL何时会使用索引来满足order by子句&#xff0c;filesort 操作会在索引不能生效的时候被用到&#xff0c;以及优化器对order by的执行计划信息。 or…

MySQL 高级 —— 索引实现的思考

引言 最近看了一个公开课&#xff0c;是有关MySQL对索引设计的思考。详细讲解了几种索引实现的设计思考与利弊辨析&#xff0c;讨论了为什么MySQL默认情况下会使用B树索引&#xff0c;B树索引又对B树做了哪些结构改进。 本片博客通过个人的学习理解和总结&#xff0c;由几种简…

MySQL 优化 —— MySQL 如何使用索引

引言 本文翻译自MySQL 官网 &#xff1a;How MySQL Uses Indexes &#xff0c;MySQL 版本 5.7 。 提升 SELECT 操作性能最好的方式就是在查询的一列或多列上建立索引。索引的行为类似指向表数据的指针&#xff0c;可以让查询能够快速判断哪个记录满足 WHERE 子句中的条件&…

MySQL 优化 —— EXPLAIN 执行计划详解

引言 本博客大部分内容翻译自MySQL 官网 Understanding the Query Execution Plan 专题。另外有一些补充&#xff0c;则来自于网课以及《高性能MySQL&#xff08;第三版&#xff09;》。 根据我们的表、字段、索引、以及 where 子句中的条件等信息&#xff0c;MySQL 优化器会…

Git 初学札记(十)—— Reset 回退的三种状态解析

引言 工作中经常会涉及到需要本地代码覆盖更新的操作。有时候可能是从远端git 上直接覆盖更新&#xff0c;或者是其他本地分支覆盖更新当前分支等等。这个时候就需要用到 reset 操作。 reset 操作分为三种类型&#xff1a;Soft、Mixed、Hard。今天我们就来说说这三种类型究竟…

MySQL 高级 —— 深入理解 InnoDB 与 MyISAM

引言 在文件系统中&#xff0c;MySQL将每个数据库&#xff08;也可以称之为schema&#xff09;保存为数据目录下的一个子目录。创建表时&#xff0c;MySQL会在数据库子目录下创建一个与表同名的.frm文件保存表的定义。因为MySQL使用文件系统的目录和文件来保存数据库和表的定义…

Ts声明ElementUI控件

初用Ts&#xff0c;有时候想获取三方控件不太会声明类型&#xff0c;记录一下使用InstanceType导入类型 例如声明一个el-select <el-form-item label"类型:" prop"year" :loading"state.loading"><el-select v-model"props.ruleF…

关于 OutOfMemoryError 的总结与解决方法

引言 本文总结自周志明的《深入理解Java虚拟机》第二章部分内容。 这部分内容&#xff0c;可以为后续性能调优方面的工作起到铺垫作用。 一、什么是 OutOfMemoryError OurOfMemory 简称“OOM”&#xff0c; 直译为“内存耗尽”或“内存溢出”&#xff0c;当然&#xff0c;并…

Windows误关闭资源管理器重启的办法

引言 有时候Windows系统在开机后&#xff0c;在桌面底部的任务栏中无法正常加载必要的网络连接图标或音量图标等&#xff0c;导致无法手动操作音量或连接网络。这时候就会需要打开“任务管理器”重新启动“资源管理器”使其重新加载这些必要的控制图标。 但是由于操作失误&am…

MySQL高级 —— 高性能索引

引言 最近一直在抱着《高性能MySQL&#xff08;第三版&#xff09;》研究MySQL相关热点问题&#xff0c;诸如索引、查询优化等&#xff0c;这阶段的学习是前一段时间MySQL基础与官方的“阅读理解”的进一步延伸。 书中第五章详细阐述了如何设计高性能的索引&#xff0c;以及索…

MySQL高级 —— 查询性能优化

引言 承接《MySQL高级 —— 高性能索引》&#xff0c;本篇博客将围绕《高性能MySQL&#xff08;第三版&#xff09;》第六章内容进行总结和概括。 与索引的部分一样&#xff0c;SQL优化也是广大程序员深入MySQL的又一条必经之路。希望通过本篇博客的总结&#xff0c;能够为我…

哈希表的大小为何最好是素数

引言 为什么散列函数采用取模运算&#xff1f;又为什么取模运算的被取模数最好是素数&#xff1f;素数是如何在取模运算中很好的规避冲突的&#xff1f; 这些问题可能困扰诸多程序员很久了。我们总是说素数可以更好的避免冲突&#xff0c;但总是对各种长篇大论的分析望而却步…

Java常用设计模式————适配器模式

引言 由于无法直接使用某个类中的方法而采取的一种中间类转换的策略。将一个类的接口转换成另一个接口&#xff0c;让原本接口不兼容的类可以兼容。 适配器模式可以分为三种&#xff1a;类适配器、对象适配器、接口适配器。它们之间的区别主要体现在适配器角色与被适配角色之…

Java常用设计模式————桥接模式

引言 在实际的业务中&#xff0c;经常会遇到多维度的概念组合&#xff0c;公园的门票&#xff0c;颐和园有年票、月票、日票&#xff0c;故宫也有年票、月票、日票。那么不同的公园和票种类型就可以视为两种不同的纬度&#xff0c;它们之间会形成相互组合的关系。 在类的设计…

Java常用设计模式————装饰者模式

引言 装饰者模式&#xff0c;又叫装饰器模式。它可以动态的将新功能附加到对象上。在对象功能扩展方面&#xff0c;它比继承更灵活&#xff0c;同时装饰者模式也体现了OCP原则。 在客户端调用使用了装饰者模式的对象时&#xff0c;就好像在使用构造器层层包裹核心对象&#x…

Java常用设计模式————组合模式

引言 组合模式&#xff0c;是一种类似递归算法的结构性设计模式&#xff0c;通过以简单的 List &#xff0c;组合本类对象&#xff0c;实现树状对象结构的“部分、整体”的层次。 它可以让调用程序不需要关心复杂对象与简单对象的区别&#xff0c;而统一地实现处理逻辑。 对…

MySQL 高级 —— MVCC 多版本并发控制

引言 MySQL的大多数事务型存储引擎实现的都不是简单的行级锁。基于提升并发性能的考虑&#xff0c;它们一般都同时实现了多版本并发控制——MVCC。包括其他数据库如Oracle等&#xff0c;由于MVCC并没有一个统一的实现标准&#xff0c;因此它们的实现原理都不尽相同。 MVCC简介…

Java常用设计模式————外观模式

引言 外观模式&#xff08;Facade Pattern&#xff09;&#xff0c;又叫“过程模式”。外观模式为子系统中的一组接口提供一个一致的入口&#xff0c;此模式定义了一个高层接口&#xff0c;这个接口使得这一组子系统更加易用。 一、案例分析 生活中有很多类似的案例&#xf…

Java常用设计模式————享元模式

引言 享元模式&#xff0c;也叫蝇量模式&#xff08;Flyweight Pattern&#xff09;。运用共享技术有效地支持大量细粒度的对象。 享元模式常用于系统底层开发&#xff0c;解决系统的性能问题。例如数据库连接池&#xff0c;里面都是创建好的连接对象&#xff0c;在这些连接对…