MySQL之查询性能优化(十一)

查询性能优化

查询优化器的提示(hint)

如果对优化器选择的执行计划不满意,可以使用优化器提供的几个提示(hint)来控制最终的执行计划。下面将列举一些常见的提示,并简单地给出什么时候使用该提示。通过在查询中加入相应的提示,就可以抗旨该查询的执行计划。关于每个提示的具体用法,建议直接阅读MySQL官方手册。有些提示和版本有直接关系。可以使用的一些提示如下:

  • 1.HIGH_PRIORITY和LOW_PRIORITY
    这个提示告诉MySQL,当多个语句同时访问某一个表的时候,那些语句的优先级相对高些、哪些语句的优先级相对低些。HIGH_PRIORITY用于SELECT语句的时候,MySQL会将此SELECT语句重新调度到所有正在等待表锁以便修改的语句之前。实际上MySQL是将其放在表的队列的最前面,而不是按照常规顺序等待。HIGH_PRIORITY还可以用于INSERT语句,其效果只是简单地抵消了全局LOW_PRIORITY设置对该语句的影响。
    LOW_PRIORITY则正好相反:它会让该语句一直处于等待状态,只要队列中还有需要访问同一个表的语句——即使是哪些比该语句还晚提交到服务器的语句。这就像一个过于礼貌地人站在餐厅门口,只要还有其他顾客在等待就一直不进去,很明显这容易把自己饿坏。LOW_PRIORITY提示在SELECT、INSERT、UPDATE和DELETE语句中都可以使用。这两个提示只对使用表锁地存储引擎有效,千万不要在InnoDB或者其他有细粒度地锁机制和并发控制的引擎中使用。即使是在MyISAM中使用也要注意,因为这两个提示会导致并发插入被禁用,可能会严重降低性能。HIGH_PRIORITY和LOW_PRIORITY经常让人感到困惑。这两个提示并不会获取更多资源让查询"积极"工作,也不会让少获取资源让查询"消极"工作。它们只是简单地控制了MySQL访问某个数据表的队列顺序。
  • 2.DELAYED
    这个提示对INSERT和REPLACE有效。MySQL会将使用该提示的语句立即返回给客户端,并将插入的行数据放入到缓冲区,然后在表空闲时批量将数据写入。日志系统使用这样的提示非常有效,或者是其他需要写入大量数据但是客户端却不需要等待单条语句完成IO的应用。这个用法有一些限制:并不是所有的存储引擎都支持这样的做法;并且该提示会导致函数LAST_INSERT_ID()无法正常工作
  • 3.STRAIGHT_JOIN
    这个提示可以放置在SELECT语句的SELECT关键字之后,也可以放置在任何两个关联表的名字之间。第一个用法是让查询中所有表按照在语句中出现的顺序进行关联。第二个用法则是固定其前后两个表的关联顺序。当MySQL没能选择正确的关联顺序的时候,或者由于可能太多的顺序导致MySQL无法评估所有的关联顺序的时候,STRAIGHT_JOIN都会很有用。在后面这种情况,MySQL可能会花费大量时间在"statistics"状态,加上这个提示则会大大减少优化器的搜索空间。可以先使用EXPLAIN语句来查看优化器选择的关联顺序,然后使用该提示来重写查询,再看看它的关联顺序。当你确定无论怎样的where条件,某个固定的关联顺序始终是最佳的时候,使用这个提示可以大大提高优化器的效率。但是在升级MySQL版本的时候,需要重新审视下这类查询,某些新的优化特性可能会因为该提示而失效
  • 4.SQL_SAMLL_RESULT和SQL_BIG_RESULT
    这两个提示只对SELECT语句有效。它们告诉优化器对GROUP BY或者DISTINCT查询如何使用临时表及排序。SQL_SMALL_RESULT告诉优化器结果集会很小,可以将结果集放在内存的索引临时表,以避免排序操作。如果是SQL_BIG_RESULT,则告诉优化器结果集可能会非常大,建议使用磁盘临时表做排序工作。
  • 5.SQL_BUFFER_RESULT
    这个提示告诉优化器将查询结果放入到一个临时表,然后尽可能地释放表锁。这和前面提到的由客户端缓存结果不同。当你没法使用客户端缓存的时候,使用服务器端的缓存通常很有效。带来的好处是无须在客户端上消耗太多的内存,还可以尽可能地释放对应的表锁。代价是,服务器端将需要更多的内存
  • 6.SQL_CACHE和SQL_NO_CACHE
    这个提示告诉MySQL这个结果集是否应该缓存在查询缓存中
  • 7.SQL_CALC_FOUND_ROWS
    严格来说,这并不是一个优化器提示。它不会告诉优化器任何关于执行计划的东西,它会让MySQL返回的结果集包含更多的信息。查询中加上该提示MySQL会计算除去LIMIT子句后这个查询要返回的结果集的总数,而实际上只返回LIMIT要求的结果集。可以通过函数FOUND_ROW()获得这个值
  • 8.FOR UPDATE和LOCK IN SHARE MODE
    这也不是真正的优化器提示。这两个提示主要控制SELECT语句的所机制,但只对实现了行级锁的存储引擎有效。使用该提示会对符合查询条件的数据行加锁。对于INSERT…SELECT语句是不需要这两个提示的,因为对于MySQL5.0和更细那版本会默认给这些记录加上读锁(可以禁用该默认行为,但不是个好主意)。唯一内置的支持这两个提示的引擎就是InnoDB。另外需要记住的是,这两个提示会让某些优化无法正常使用,例如索引覆盖扫描。InnoDB不能再不访问主键的情况下排他地锁定行,因为行的版本信息保存在主键中。糟糕的是,这两个提示经常被滥用,很容易造成服务器的锁争用问题应该尽可能地避免使用这两个提示,通常都有其他更好的方式可以实现同样的目的。
  • 9.USE INDEX、IGNORE INDEX和FORCE INDEX
    这几个提示会告诉优化器使用或者不适用哪些索引来查询记录(例如,在决定关联顺序的时候使用哪个索引)。在MySQL5.0和更早的版本,这些提示并不会影响到优化器选择哪个索引进行排序和分组,在MySQL5.1和之后的版本可以通过新增选项FOR ORDER BY和FOR GROUP BY来指定是否对排序和分组有效。FORCE INDEX和USE INDEX基本相同,除了一点:FORCE INDEX会告诉优化器全表扫描的成本会远远高于索引扫描,哪怕实际上该索引用处不大。当发现优化器选择了错误的索引,或者因为某些原因(比如在不适用ORDER BY的时候希望结果有序)要使用另一个索引时,可以使用该提示。

MySQL5.0和更新版本中,新增了一些参数用来控制优化器的行为:

  • 1.optimizer_search_depth
    这个参数控制优化器在穷举执行计划时的限度。如果查询长时间处于"Statistics"状态,那么可以考虑调低此参数。
  • 2.optimizer_prune_level
    该参数默认是打开的,这让优化器会根据需要扫描的行数来决定是否跳过某些执行计划
  • 3.optimizer_switch
    这个变量包含了一些开启/关闭优化器特性的标志位。例如在MySQL5.1中可以通过这个参数来控制禁用索引合并的特性

前两个参数是用来控制优化器可以走的一些"结晶"。这些结晶可以让优化器在处理非常复杂的SQL语句时,仍然可以很搞笑,但这也可能让优化器错过一些真正最优的执行计划。所以应该根据实际需要来修改这些参数。

MySQL升级后的验证

在优化器面前耍一些"小聪明"是不好的。这样做收效甚小,但是却给维护带来了很多额外的工作量。在MySQL版本升级的时候,这个问题就很突出了,你设置的"优化器提示"很可能会让新版的优化策略失效。MySQL5.0版本引入了大量优化策略,在还没有正式发布的5.6版本中,优化器的改进也是近些年来最大的一次改进。如果要更新到这些版本,当然希望能够从这些改进中受益。新版MySQL基本上在各个方面都有非常大的改进,5.5和5.6这两个版本尤为突出。升级操作一般来说都很顺利,但仍然建议仔细检查各个细节,以防止一些边界情况影响你的应用程序。不过还好,要避免这些,你不需要符出太多的经历,使用Percona ToolKit中的pt-upgrade工具,就可以检查在新版本中运行的SQL是否和老版本一样,返回相同的结果

优化特定类型的查询

接下来将介绍如何优化特定类型的查询,对于未来MySQL的版本未必适用。毫无疑问,某一天优化器自己也会实现这里列出的部分或者全部优化技巧。

优化COUNT()查询

COUNT()聚合函数,以及如何优化使用了该函数的查询,很可能是MySQL中最容易被误解的10个话题之一。在网上随便一搜就能看到很多错误的理解,可能比我们想象的多得多。在做优化之前,先来看看COUNT()函数真正的作用是什么

  • 1.COUNT()的作用
    COUNT()是一个特殊的函数,有两种非常不同的作用:它可以统计某个列值的数量,也可以统计行数,在统计列值时要求列值是非空的(不统计NULL).如果在COUNT()的括号中指定了列或者列的表达式,则统计的就是这个表达式有值的结果数(而不是NULL).因为很多人对NULL理解有问题,所以这里很容易产生误解。COUNT()的另一个作用是统计结果集的行数。当MySQL确认括号内的表达式值不可能为空时,实际上就是在统计行数。最简单的就是当我们使用COUNT()的时候,这种情况下通配符并不会像我们猜想的那样扩展成所有的列,实际上,它会忽略所有的列而直接统计所有的行数。
    我们发现一个最常见的错误就是,在括号内指定了一个列却希望统计结果集的行数。如果希望知道的是结果集的行数,最好使用COUNT(*),这样些意义清晰,性能也会很好
  • 2.关于MyISAM的神话
    一个容易产生的误解就是:MyISAM的COUNT()函数总是非常快,不够这是有前提条件的,即只有没有任何WHERE条件的COUNT()才非常快,因为此时无须实际地去计算表的行数。MySQL可以利用存储引擎的特性直接获得这个值。如果MySQL知道某列col不可能为NULL值,那么MySQL内部会将COUNT(col)表达式优化为COUNT()。当统计带WHERE子句的结果集行数,可以是统计某个列值得数量时,MyISAM得COUTN()和其他存储引擎没有任何不同,就不再有神话般得速度了,所以在MyISAM引擎表上执行COUNT()有时候比别得引擎块,有时候比别的引擎慢,这受很多因素影响,要视具体情况而定
  • 3.简单的优化
    有时候可以使用MyISAM在COUNT(*)全表非常快得这个特性,来加速一些特定条件的COUNT()查询。在下面的例子中,我们使用标准数据库world来看看如何快速查找到所有ID大于5的城市。可以像下面这样来写这个查询:
mysql> SELECT COUNT(*) FROM world.City WHERE ID > 5;

通过SHOW STATUS的结果可以看到该擦汗寻需要扫描4097行数据。如果将条件反转一下,先找到ID小于等于5的城市数,然后用总城市数一减就能得到同样的结果,却可以将扫描的行数减少到5行以内:

mysql> SELECT (SELECT COUNT(*) FROM world.City) - COUNT(*)-> FROM world.City WHERE ID <= 5;

这样做可以大大减少需要扫描的行数,是因为在查询优化阶段会将其中的子查询当作一个常数来处理。在邮件组和IRC聊天频道中,通常会看到这样的问题:如何在同一个查询中统计同一个列的不同值的数量,以减少查询的语句量。例如,假设可能需要通过一个查询返回各种不同颜色的商品数量,此时不能使用OR语句(比如SELECT COUNT(color=‘blur’ OR color=‘red’) FROM items;)因为这样做就无法区分不同颜色的商品数量;也不能在WHERE条件中指定颜色(比如SELECT COUNT(*) FROM items WHERE color=‘blue’ AND color = ‘RED’)因为颜色的条件是互斥的。下面的查询可以在一定程度上解决这个问题。

mysql> SELECT SUM(IF(color='blue', 1,0)) AS blue, SUM(IF(color='red',1,0)) AS red FROM items;

也可以使用COUNT()而不是SUM()实现同样的目的,只需要将满足条件设置为真,不满足条件设置为NULL即可

mysql> SELECT COUNT(color = 'blue' OR NULL) AS blue, COUNT(color= 'read' OR NULL) AS red FROM items;

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

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

相关文章

【AIGC+CAD】革新建筑、室内设计与建模领域的GenAI产品

一、产品定位 Augrade,一款专为建筑、室内设计和建模行业打造的AI CAD自动化工具。它凭借先进的AI技术,将2D蓝图迅速转化为精确的3D CAD模型,同时提供设计、成本分析的自动化以及全面的文档生成服务。Augrade致力于简化设计流程,确保技术可行性,并促进跨团队、跨工具的协…

Java Web学习笔记19——Ajax介绍

Ajax: 概念&#xff1a;Asynchronous JavaScript And XML 异步的JavaScript和XML。 作用&#xff1a; 1&#xff09;数据交换&#xff1a;通过Ajax可以给服务器发送请求&#xff0c;并获得服务器的响应数据。 2&#xff09;异步交互&#xff1a;可以在不重新加载页面的情况…

Hadoop+Spark大数据技术 实验11 Spark 图

17周期末考试 重点从第五章 scala语言开始 比如&#xff1a;映射&#xff08;匿名函数&#xff09; 11.3.1创建属性图 import org.apache.spark.graphx._ import org.apache.spark.rdd.RDD //创建一个顶点集的RDD val users: RDD[(VertexId ,(String,String))] sc.paralle…

基于思通数科大模型的设备隐患智能检测:图像处理与声音分析的融合应用

在现代工业生产中&#xff0c;设备的稳定运行对保障生产效率和产品质量至关重要。然而&#xff0c;设备的老化、磨损以及异常状态的检测往往需要大量的人力和物力。思通数科大模型结合图像处理技术和声音分析技术&#xff0c;为设备隐患检测提供了一种自动化、高效的解决方案。…

一个训练好的神经网络的模型文件的内容主要是什么信息呢?请用大白话举例说明( 百度 API 回答 )

训练好的神经网络的模型文件&#xff0c;其实保存了神经网络学习到的“知识”和“经验”。用大白话来说&#xff0c;它主要保存了以下几类信息&#xff1a; 网络结构&#xff1a;这就像是神经网络的“骨架”或者“蓝图”&#xff0c;告诉计算机这个神经网络有哪些层&#xff0…

Docker 管理 | 代理配置、内网共享和 Harbor 部署

唠唠闲话 在现代软件开发和运维中&#xff0c;容器技术已经成为构建、部署和管理应用程序的标准工具。然而&#xff0c;在实际操作中&#xff0c;我们常常需要面对一些常见的挑战&#xff0c;如容器访问外部资源的代理配置、内网环境下的镜像共享以及企业级镜像管理。 本教程…

websocket 前端项目js示例

websocket前端 和服务端websocket通信示例&#xff0c; 前端直接使用h5的内置对象 WebSocket 来创建和管理 WebSocket 连接&#xff0c;以及可以通过该连接发送和接收数据。 这个对象都是是事件方式来处理和与后端交互数据&#xff0c; 他们分别是 onopen打开, onclose关闭, o…

关键字、保留字、标识符

关键字 关键字是被 Java 赋予了特定含义的英文单词。 关键字的字母全部小写。 保留字 现有的 Java 版本尚未使用&#xff0c;但是以后版本可能会作为关键字使用。自己命名标识符时需要避免使用这些保留字。 保留字有&#xff1a;byValue, cast, future, generic, inner, op…

Spring Boot整合WebSocket和Redis实现直播间在线人数统计功能

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

高精度加法的实现

这是C算法基础-基础算法专栏的第七篇文章&#xff0c;专栏详情请见此处。 引入 在C语言中&#xff0c;int的可存储数据范围是-2147483648~2147483647&#xff0c;long long的可存储数据范围是-9223372036854775808~9223372036854775807&#xff0c;但是如果一些数据比long long…

【TensorFlow深度学习】实现Actor-Critic算法的关键步骤

实现Actor-Critic算法的关键步骤 实现Actor-Critic算法的关键步骤&#xff1a;强化学习中的双剑合璧Actor-Critic算法简介关键实现步骤代码示例&#xff08;使用TensorFlow&#xff09;结语 实现Actor-Critic算法的关键步骤&#xff1a;强化学习中的双剑合璧 在强化学习的广阔…

Qt下调用Snap7库与西门子PLC通信

文章目录 前言一、Snap7源码下载二、Snap7的dll常用函数功能介绍三、Snap7Lib.pri模块的封装四、下载链接总结 前言 本文主要讲述了在Qt下调用Snap7库与西门子PLC进行通信&#xff0c;在这里将Snap7的源码与动态库整合在一起封装了一个自己的Snap7Lib.pri子模块&#xff0c;方…

java-集合的使用 1

Java 中的集合框架&#xff08;Collection Framework&#xff09;是 Java API 的一部分&#xff0c;提供了对各种集合数据结构的支持。集合框架使得 Java 程序员能够方便地处理集合数据&#xff0c;而不必担心底层的实现细节。Java 集合框架包括一系列接口和类&#xff0c;用于…

【Python】读取文件夹中所有excel文件拼接成一个excel表格 的方法

我们平常会遇到下载了一些Excel文件放在一个文件夹下&#xff0c;而这些Excel文件的格式都一样&#xff0c;这时候需要批量这些文件合并成一个excel 文件里。 在Python中&#xff0c;我们可以使用pandas库来读取文件夹中的所有Excel文件&#xff0c;并将它们拼接成一个Excel表…

尝试使用blazor(一)吐槽blazor,未开始之前,先吐为敬

为什么要写一点关于blazor的文章呢?其实是没什么人看的&#xff0c;我知道blazor目前在国内使用的人数&#xff0c;恐怕一辆大巴车都坐不满。非常冷门&#xff0c;我刚用blazor遇到问题&#xff0c;花钱找人解决&#xff0c;找了国内几个著名的平台&#xff0c;几乎没人会blaz…

【docker】centos7配置docker镜像阿里云加速

国内从 DockerHub 拉取镜像有时会遇到困难&#xff0c;由于网络原因&#xff0c;下载一个Docker官方镜像可能会需要很长的时间&#xff0c;甚至下载失败。此时可以配置镜像加速器。Docker 官方和国内很多云服务商都提供了国内加速器服务。 测试了几次阿里云的加速是最快的。 …

Golang | Leetcode Golang题解之第131题分割回文串

题目&#xff1a; 题解&#xff1a; func partition(s string) (ans [][]string) {n : len(s)f : make([][]int8, n)for i : range f {f[i] make([]int8, n)}// 0 表示尚未搜索&#xff0c;1 表示是回文串&#xff0c;-1 表示不是回文串var isPalindrome func(i, j int) int8…

Hive 面试题(五)

1. 简述分区表和分桶表的区别 &#xff1f; 分区表&#xff08;Partitioned Table&#xff09;和分桶表&#xff08;Bucketed Table&#xff09;都是Hive中用于优化查询性能的数据组织方式&#xff0c;但它们在概念和用途上有所不同&#xff1a; 分区表&#xff08;Partition…

安装 JDK 8

安装包 百度网盘 提取码&#xff1a;6666 安装步骤 安装路径不要有中文或者特殊符号如空格等。 双击安装包开始安装。 更改安装路径&#xff1a; 跳出一个页面&#xff0c;安装公共 JRE&#xff1a; 配置环境变量&#xff1a; 配置成功&#xff1a; 去掉自动更新

git子模块

1 子模块管理的关键文件和配置 在 Git 中使用子模块时&#xff0c;Git 会利用几个特殊的文件和配置来管理子模块。以下是涉及子模块管理的关键文件和配置&#xff1a; 1.1 .gitmodules 这是一个文本文件&#xff0c;位于 Git 仓库的根目录下。它记录了子模块的信息&#xff…