赞
踩
如果我们希望mysql能以更高的性能运行查询,我们就需要了解mysql是如何优化和执行查询的。如此我们在实际的查询优化工作上就能遵循一些原则让优化器能够按照预想的合理的方式运行。
下面我们看看mysql执行一个查询的真实过程:
客户端发送查询语句给服务器
服务器先检查缓存,如果缓存命中,则返回缓存结果,否则进入下一阶段
服务器进行sql解析、预处理,再由优化器生成对应的执行计划
mysql根据优化器生成的执行计划,调用存储引擎的API来执行查询
将结果返回给客户端
mysql发送查询语句给服务器、服务器返回查询结果给客户端,要了解这两部操作的过程,需要知道mysql客户端和服务器的通信协议。
mysql客户端和服务器端的通信协议是半双工的,即要么是服务器向客户端发送数据,要么是客户端向服务器发送数据,两个动作不能同时进行。客户端用一个数据包想服务器端发送请求,如果我们请求的SQL语句很长,如批量插入数据时,这会使客户端发送请求占用的时间很长,而且如果语句超出max_allowed_packet mysql 会抛出错误信息,为此一般我们要把它拆分成多个小的sql语句处理,然后等待操作结果;而服务器响应客户端的数据,一般会响应比较多的数据,这些数据由多个数据包组成,且客户端必须完整的接收整个返回结果,然后才能让服务器端停止发送数据,
这要注意mysql库函数的应用,多数链接mysql的库函数都可以获得全部结果集并缓存到内存中。一般情况下,缓存到内存中的数据有利于mysql性能提升,但是如果返回的结果集过大,库函数就需要花很多的时间和内存来存储结果集。
mysql查询状态:对于一个mysql链接,或一个线程,任何一个时刻都有一个状态,标识mysql当前的动作。可以使用 show full processing 命令查看mysql状态。
下面是mysql查询中的集中状态:
在解析一个查询语句之前,如果查询缓存是打开的,mysql会优先检查这个查询是否命中缓存中的数据。且这个查询是同通过一个对大小写敏感的哈希查找实现的,查询和缓冲中的查询即使有一个字节不同,也不会匹配缓存结果。
如果查询命中缓存,则不会再去解析sql语句,也不会后后续的3、4步的操作,而是直接返回结果,大大提高查询效率。
查询的生命周期的下一步是将一个SQL转换成一个执行计划,MySQL再按照这个执行计划和存储引擎进行交互。这包括多个子阶段:解析SQL、预处理、优化SQL执行计划。这些过程中任何出错都可能终止查询。
语法解析器:mysql先通过关键字将SQL语句进行解析,并生成对应的解析树,并对起进行校验。
预处理:根据Mysql规则进一步检查解析树的合法性。
查询优化器:优化器将解析树转化成执行计划。而一个查询可以有多种执行方式,优化器的作用就是从中找到最优执行计划。查询优化器是mysql中非常重要且复杂的部件,这里简单介绍一下优化器的一些特点。
Mysql查询优化器是基于成本的优化器,它会预测一个查询使用某种计划的成本,并选择成本最小的一个。
下面这些原因可能会导致Mysql选择错误的执行计划:
mysql优化器优化策略分为静态优化和动态优化:静态优化可以直接对解析树进行分析并完成优化,不依赖于特别的数值,依次完成后就一直有效,如通过简单的代数变换将where条件转换成另一种等价形式; 动态优化和查询的上下文有关,也可能和多种其他因素有关,如where条件的取值、索引中条目对应数据行数等,它需要每次在查询的时候进行评估,可以理解为 “运行时优化”。
mysql处理的优化类型有:
这一阶段是真正执行查询操作,执行引擎用来开始真正执行查询操作的工具。它根据之前生成的执行计划,按照执行计划逐步执行。
查询执行的最后一个阶段是将结果返回给客户端。及时查询不需要返回结果给客户端,MySQL仍然会返回这个查询的信息,如该查询影响到的行数。
在这个阶段中,如果查询是可以被缓存的,那么MySQL在这个阶段也将会被存放到查询缓存中。
MySQL将结果集返回给客户端是一个增量地、逐步返回的过程。这样做有两个好处:服务器端无需存储太多的结果,也就不会因为要返回太多结果而消耗太多内存。这样的处理也会让MySQL客户端第一时间获得返回的结果。
结果集中的每一行都会以一个满足MySQL客户端/服务器通信协议的封包发送,再通过TCP协议进行传输,在TCP传输中,可能会对MySQL的封包进行缓存然后批量传输
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。