MySQL之查询性能优化(四)

查询性能优化

MySQL客户端/服务器通信协议

一般来说,不需要去理解MySQL通信协议的内部实现细节,只需要大致理解通信协议是如何工作的。MySQL客户端和服务器之间的通信协议是"半双工"的,这意味着,在任何一个时刻,要么是由服务器向客户端发送数据,要么是由客户端向服务器发送数据,这两个动作不能同时发生。所以,我们也无法也无须将一个消息切成小块独立来发送。这种协议让MySQL通信简单快速,但是也从很多地方限制了MySQL.一个明显的限制是,这意味着没法进行流量控制。一旦一端开始发送消息,另一端要接收完整个消息才能响应它。这就像来回抛球的游戏:在任何时刻,只有一个人能控制球,而且只有控制球的人才能将球抛回去(发送消息)。一旦客户端发送了请求,它能做的事情就只是等待结果了。相反的,一般服务器响应给用户的数据通常很多,由多个数据包组成。当服务器开始响应客户端请求时,客户端必须完整接收整个返回结果,而不能简单地只取前面几条结果,然后让服务器停止发送数据。这种情况下,客户端若接收完整的结果,然后取前面几条需要的结果,或者接收完几条结果后就"粗暴"地断开连接,都不是好注意。这也是在必要的时候一定要在查询中加上LIMIT限制的原因。换一种方式解释这种行为:当客户端从服务器取数据时,看起来是一个拉数据的过程,但实际上是MySQL在向客户端推送数据的过程。客户端不断地接收从服务器推送的数据,客户端也没法让服务器停下来。客户端像是"从消防管喝水"(这是一个术语)。多数连接MySQL的库函数都可以获得全部结果集并缓存到内存力,还可以逐行获取需要的数据。默认一般是获得全部结果集并缓存到内存中。MySQL通常需要等所有的数据都已经发生给客户端才能释放这条查询所占用的资源,所以接收全部结果并缓存通常可以减少服务器的压力,让查询能够早点结束、早点释放相应的资源。
当使用多数连接MySQL的库函数从MySQL获取数据时,其结果看起来都像时从MySQL服务器获取数据,而实际上都是从这个库函数的缓存获取数据。多数情况下这没什么问题,但是如果需要返回一个很大的结果集的时候,这样做并不好,因为库函数会花很多时间和内存来存储所有的结果集。如果能够尽早开始处理这些结果集,就能大大减少内存的消耗,这种情况下可以不适用缓存来记录结果而是直接处理。这样做的缺点是,对于服务器来说,需要查询完成后才能释放资源,所以在和客户端交互的整个过程中,服务器的资源都是被这个查询搜占用的(你可以使用SQL_BUFFER_RESULT)
我们看啊可能当使用PHP的时候是什么情况。首先,下面是我们连接MySQL的通常写法:

<?php
$link = mysql_connect('localhost','user','p4ssword');
$result = mysql_query('SELECT * FROM HUGE_TABLE', $link);
$while($row = mysql_fetch_array($result)) {
// Do something with result
}
?>

这段代码看起来像是只有当你需要的时候,才通过循环从服务器取出数据。而实际上,在上面的代码中,在调用mysql_query()的时候,PHP就已经将整个结果缓存到内存中。下面的while循环只是从这个缓存中逐行取出数据,相反如果使用下面的查询,用mysql_unbuffered_query()代替mysql_query(),PHP则不会缓存结果:

<?php
$link = mysql_connect('localhost', 'user', 'p4ssword');
$result = mysql_unbuffered_query('SELECT * FROM HUGE_TABLE', $link);
while($row = mysql_fetch_array($result)) {
//Do something with result
}
?>

不同的编程语言处理缓存的方式不同。例如,在Perl的DBD:mysql驱动中需要指定C连接库的mysql_use_result属性(默认是mysql_buffer_result)。下面是一个例子:

#!usr/bin/perl
use DBI;
my $dbh = DBI->connect('DBI:mysql:;host=localhost', 'user', 'p4ssword');
my $sth = $dbh->prepare('SELECT * FROM HUGE_TABLE', {mysql_use_result => 1});
$sth -> execute();
while (my $row = $sth->fetchrow_array()) {
# Do something with result
}

注意到上面的prepare()调用指定了mysql_use_result属性为1,所以应用将直接"使用"返回的结果集而不会将其缓存。也可以在连接MySQL的时候指定这个属性,这会让整个连接都使用不缓存的方式处理结果集:

my $dbh = DBI->connect('DBI:mysql:;mysql_use_result=1', 'user','p4ssword');

查询状态

在这里插入图片描述

对于一个MySQL连接,或者说一个线程,任何时刻都有一个状态,该状态标识了MySQL当前正在做什么。有很多种方式能查看当前的状态,最简单的是使用SHOW FULL PROCESSLIST命令(该命令返回结果中的Command列就表示当前的状态)。在一个查询的生命周期中,状态会变化很多次。MySQL官方手册中对这些状态值的含义有权威的解释,下面将这些状态列出来,并做一个简单的解释.

  • 1.Sleep
    线程正在等待客户端发送新的请求
  • 2.Query
    线程正在执行查询或者正在将结果发送给客户端
  • 3.Locked
    在MySQL服务器层,该线程正在等待表锁。存储引擎级别实现的锁,例如InnoDB的行锁,并不会体现在线程状态中。对于MyISAM来说这是一个比较典型的状态,但在其他没有行锁的一你请中也会经常出现
  • 4.Analyzing and statistics
    线程正在收集存储引擎的统计洗脑洗,并生成查询的执行计划
  • 5.Copying to tmp table [on disk]
    线程正在执行查询,并且将结果集都复制到一个临时表中,这种状态一般要么是在做GROUP BY操作,要么是文件排序操作,或者UNION操作。如果这个状态后面还有"on disk"标记,那表示MySQL正在将一个内存临时表放到磁盘上
  • 6.Sorting result
    线程正在对结果集进行排序
  • 7.Sending data
    这表示多种情况:线程可能在多个状态之间传送数据,或者在生成结果集,或者在向客户端返回数据。

了解这些状态的基本含义非常有用,这可以让我们很快地了解当前"谁正在持球"。在一个繁忙的服务器上,可能会看到大量的不正常的状态。例如statstics正占用大量的时间。这通常表示,某个地方有异常了

查询缓存(这里是指Query Cache)

在解析一个查询语句之前,如果查询缓存是打开的,那么MySQL会优先检查这个查询是否命中查询缓存中的数据。这个检查是通过一个对大小写敏感的哈希查找实现的。查询和缓存中的查询即使只有一个字节不同,那也不会匹配缓存结果(Percona版本的MySQL中提供了一个新的特性,可以在计算查询语句哈希值时,先将注释移除再计算哈希值,这对于不同注释的相同查询可以命中相同的查询缓存结果)。这种情况下查询就会进入下一个阶段的处理。如果当前的查询恰好命中了查询缓存,那么再返回查询结果之前MySQL会检查一次用户权限。这仍然时无须解析查询SQL语句的,因为在查询缓存中已经存放了当前查询需要访问的表信息。如果权限没有问题,MySQL会跳过所有其他阶段,直接从缓存中拿到结果并返回给客户端。这种情况下,查询不会被解析,不用生成执行计划,不会被执行

查询优化处理

查询的生命周期的下一步时将一个SQL转换成一个执行计划,MySQL再依照这个执行计划和存储引擎进行交互。这包括多个子阶段:解析SQL、预处理、优化SQL执行计划。这个过程中任何错误(例如语法错误)都可能终止查询。接下来选择性地介绍其中几个独立的部分,在实际执行中,这几部分可能一起执行也可能单独执行。目的是帮助大家理解MySQL是如何执行查询,以便写出更优秀的查询。

语法解析器和预处理

首先,MySQL通过关键字将SQL语句进行解析,并生成一棵对应的"解析树",MySQL解析器将使用MySQL语法规则验证和解析查询,例如,它将验证是否使用错误的关键字,或者使用关键字的顺序是否正确等,再或者它还会验证引号是否能前后匹配。预处理器则根据一些MySQL规则进一步检查解析树是否合法,例如,这里将检查数据表和数据列是否存在,还会解析名字和别名,看看它们是否有歧义,下一步预处理器会验证权限。这通常很快,除非服务器上有很多的权限配置。

查询优化器

现在语法书被认为是合法的了,并且由优化器将其转化成执行计划。一条查询可以有很多种执行方式,最后都返回相同的结果。优化器的作用就是找到这其中最好的执行计划。MySQL使用基于成本的优化器,它将尝试预测一个查询使用某种执行计划时的成本,并选择其中成本最小的一个。最初,成本的最小单位是随机读取一个4K数据页的成本,后来(成本计算公式)变得更加复杂,并且引入了一些"因子"来估算某些操作的代价,如当执行一次WHERE条件比较的成本.可以通过查询当前会话的Last_query_cost的值来得知MySQL计算的当前查询的成本;

mysql> SELECT SQL_NO_CACHE COUNT(*) FROM film_actor;
+----------+
| COUNT(*) |
+----------+
|     5462 |
+----------+
1 row in set (0.07 sec)
mysql> SHOW STATUS LIKE 'Last_query_cost';
+-----------------+-------------+
| Variable_name   | Value       |
+-----------------+-------------+
| Last_query_cost | 1104.399000 |
+-----------------+-------------+
1 row in set (0.07 sec)

这个结果表示MySQL的优化器认为大概需要做1040个数据页的随机查找才能完成上面的查询。这是根据一系列的统计信息计算得来的:每个表或者索引的页面个数、索引的基数(索引中不同值得数量)、索引和数据行得长度、索引分布情况。优化器再评估成本的时候并不考虑任何层面的缓存,它假设读取任何数据都需要一次磁盘IO.有很多种原因会导致MySQL优化器选择错误的执行计划,如下所示:

  • 1.统计信息不准确。MySQL依赖存储引擎提供的统计信息来评估成本,但是有的存储引擎提供的信息是准确的,有的偏差可能非常大。例如,InnoDB因为其MVCC的架构,并不能维护一个数据表的行数的精确统计信息
  • 2.执行计划种的成本估算不等同于实际执行的成本,所以即使统计信息准确,优化器给出的执行计划也可能不是最优的。例如有时候某个执行计划虽然需要读取更多的页面,但是它的成本却更小。因为如果这些页面都是顺序读或者这些页面已经在内存种的花,那么它的访问成本将很小。MySQL层面并不知道哪些页面在内存中、哪些在磁盘上,所以查询实际执行过程中到底需要多少次物理IO是无法得知的。
  • 3.MySQL的最优可能和你想的最优不一样。你可能希望执行时间尽可能的短,但是MySQL只是基于其成本模型选择最优的执行计划,而有些时候这并不是最快的执行方式。所以,这里我们看到的根据执行成本来选择执行计划并不是完美的模型
  • 4.MySQL从不考虑其他并发执行的查询,这可能会影响到当前查询的速度
  • 5.MySQL也并不是任何时候都是基于成本的优化。有时也会给予一些固定的规则,例如,如果存在全文搜索的MATCH()子句,则在存在全文索引的时候就使用全文索引。即使有时候使用别的索引和WHERE条件可以远比这种方式要快,MySQL也仍然会使用对应的全文索引。
  • 6.MySQL不会考虑不受其控制的操作的成本,例如执行存储过程或者用户自定义函数的成本
  • 7.后面我们还会看到,优化器有时候无法去估算所有可能的执行计划,所以它可能错过实际上最优的执行计划

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

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

相关文章

神经网络与深度学习——第15章 序列生成模型

本文讨论的内容参考自《神经网络与深度学习》https://nndl.github.io/ 第15章 序列生成模型&#xff0c;习题还没做先存在这里。 序列生成模型 序列概率模型 序列生成 N元统计模型 深度序列模型 模型结构 嵌入层 特征层 输出层 参数学习 评价方法 困惑度 BLEU算法 ROUGE算法 序…

Aethir: 破局算力瓶颈,构建AI时代去中心化云基础设施

科技的每一次飞跃都在重新塑造世界&#xff0c;而近年来&#xff0c;跨越式的技术革新再次引发了深刻的变革&#xff0c;那就是人工智能&#xff08;AI&#xff09;。 人工智能已然超越了此前的所有技术概念&#xff0c;成为了继互联网之后的下一个巨大浪潮。从自动驾驶汽车到…

每天复习一点小CTF知识(6.4)

NSSCTF/[FSCTF 2023]夜深人静的时候也会偷偷emo 直接爆破压缩包&#xff0c;先来数字 解压好&#xff0c;一个flag.mp3 mp3隐写&#xff0c;直接干 得一个txt文件直接开

宇泰485中继器光电隔离防雷 工业级RS485信号放大器 UT-2209正品

品牌&#xff1a;other/其他 型号&#xff1a;UT-2209 上市时间&#xff1a;2018-01-01 颜色分类&#xff1a;蓝色 信号延长器,工业级,高性能,RS-485光电隔离中继器,兼容RS-485标准,延长通信距离,即插即用. 性能特点: 内置光电隔离器及DC/DC隔离模块. 采用TVS瞬态电…

读书-《蛤蟆先生去看心理医生》

书名蛤蟆先生去看心理医生作者罗伯特戴博德状态阅读中简介该书借用《柳林风声》的故事主角蛤蟆先生&#xff0c;讲述了他接受心理咨询的故事。作者通过陷入抑郁的蛤蟆先生和心理咨询师苍鹭的互动&#xff0c;探索蛤蟆先生爱炫耀、自卑性格和抑郁情绪的来源&#xff0c;指出童年…

【Python】 如何在Python中使用小数步长值的`range()`函数?

在Python编程中&#xff0c;range()函数是一个非常常用的工具&#xff0c;它用于生成一个整数序列。然而&#xff0c;标准的range()函数只能接受整数作为步长值&#xff0c;这在某些情况下可能会限制其应用。幸运的是&#xff0c;Python提供了一些方法来实现使用小数步长的rang…

优思学院|六西格玛绿带与黑带知识体系的比较,哪个更适合你?

六西格玛作为一种广泛应用的质量管理方法&#xff0c;通过减少缺陷和变异来提高输出质量。为了实现这些目标&#xff0c;六西格玛采用数据驱动的DMAIC&#xff08;定义、测量、分析、改进、控制&#xff09;方法。在六西格玛的实施过程中&#xff0c;绿带和黑带是两个关键角色。…

【代码随想录】【算法训练营】【第28天】 [93]复原IP地址 [78]子集 [90]子集II

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 LeetCode。 day 28&#xff0c;工作的周二~ 题目详情 [93] 复原 IP 地址 题目描述 93 复原 IP 地址 解题思路 前提&#xff1a;分割问题 思路&#xff1a;回溯算法&#xff0c;确定每次递归回溯的分割位置…

小短片创作-理论知识(五)

1、网格体绘制 1.UE5打开Megascan插件的材质混合器&#xff0c;创建混合材质&#xff0c;最多选择3个材质进行混合&#xff0c; 2.通过模式->网格体绘制&#xff0c;进入网格体绘制模式&#xff0c;通过select选择一个平面进行绘制&#xff0c;然后通过paint进行绘制&am…

【Mac】Keyboard Maestro for Mac(键盘大师)软件介绍及安装教程

软件介绍 Keyboard Maestro for mac&#xff08;键盘大师&#xff09;是目前Mac OS平台上功能最为齐全的Mac键盘增强工具&#xff0c;它能将你的Keyboard作用发挥到极致&#xff0c;可以根据命令或计划自动执行简单或复杂的应用程序或网站&#xff0c;文本或图像。使用Keyboar…

【TPAMI-2024】EfficientTrain++帮你降低网络训练的成本

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言论文更容易学习的模式:频域易于学习的模式:空间域统一的训练课程 EFFICIENTTRAIN计…

RIP v2路由安全认证综合实验

RIP v2路由安全认证综合实验 实验拓扑&#xff1a; 实验要求&#xff1a;通过认证防范攻击者获得通信设备的相关信息。 实验步骤&#xff1a; 1.完成基本配置 sys Enter system view, return user view with CtrlZ. [Huawei]sys AR1 [AR1]undo in e Info: Information center…

【电子书赠送福利】蘇小沐电子数据取证实务教程!风吹哪页读哪页,哪页不会撕哪页!

【电子书赠送福利】蘇小沐电子数据取证实务教程&#xff01;风吹哪页读哪页&#xff0c;哪页不会撕哪页&#xff01; 合并文章的时候才发现自己写了那么多&#xff0c;受限于时间&#xff0c;第一次合集版本只收录了已发博客的三分之二左右&#xff0c;暂时先这样&#xff01;…

外汇天眼:Bitpanda 扩大与德意志银行的合作

金融科技独角兽Bitpanda正在扩大与德意志银行的合作&#xff0c;为德国用户提供实时支付解决方案&#xff0c;以处理进出交易。 这种基于API的账户解决方案将使Bitpanda能够访问德国的IBAN账户&#xff0c;优化和增强用户体验&#xff0c;同时确保信任、速度和效率。 这只是Bi…

七大战略性新兴产业崭露头角:新能源电燃灶或将成为未来厨房新宠

近日&#xff0c;在国家发布的七大战略性新兴产业名单中&#xff0c;新能源产业赫然在列&#xff0c;作为其中的重要组成部分&#xff0c;华火新能源电燃灶凭借其独特的优势&#xff0c;正逐渐走进人们的视野&#xff0c;有望成为未来厨房的新宠。 华火新能源电燃灶作为清洁能源…

NeuralForecast 多变量的处理 包括训练和推理

NeuralForecast 多变量的处理 包括训练和推理 flyfish 两个excel表格合并后的结果 unique_id ds y ex_1 ex_2 ex_3 ex_4 0 HUFL 2016-07-01 00:00:00 -0.041413 -0.500000 0.166667 -0.500000 -0.001370 1 …

Houdini pbd_constraints.h的文件位置

Houdini安装目录下的houdini\vex\include文件夹 C:\Program Files\Side Effects Software\Houdini 19.5.716\houdini\vex\include

17.调用游戏本身的hp减伤害函数实现秒杀游戏角色

上一个内容&#xff1a;16.在目标进程构建CALL执行代码 16.在目标进程构建CALL执行代码在它的代码上进行的更改&#xff0c;它的callData变量中的代码不完善一个完整的函数是由return的处理器执行到return会返回如果执行不到会继续往下走&#xff0c;直到执行不下去或者执行到…

Facebook开户 | Facebook海外三不限的价值

在当今数字化时代&#xff0c;海外数字营销已经成为企业推广和品牌建设的重要手段。在这个过程中&#xff0c;社交媒体平台扮演着至关重要的角色&#xff0c;而Facebook作为全球最大的社交媒体平台之一&#xff0c;其海外三不限账户近年来引起了越来越多数字营销从业者的关注。…

技术积累1:Java容错机制

如何优雅地重试 原创 赵九文 字节跳动技术团队 2021-01-05 10:01 背景 在微服务架构中&#xff0c;一个大系统被拆分成多个小服务&#xff0c;小服务之间大量 RPC 调用&#xff0c;经常可能因为网络抖动等原因导致 RPC 调用失败&#xff0c;这时候使用重试机制可以提高请求的…