MySQL架构__查询执行过程简单分析

借鉴于大佬,进行总结,用于个人记录复习

https://blog.csdn.net/chenshun123/article/details/79677037

MySQL逻辑架构
在这里插入图片描述

MySQL逻辑架构整体分为三层 :
1.客户端 : 并非MySQL所独有,诸如 : 连接处理、授权认证、安全等功能均在这一层处理
2.核心服务 : 包括查询解析、分析、优化、缓存、内置函数(比如 : 时间、数学、加密等函数),所有的跨存储引擎的功能也在这一层实现 : 存储过程、触发器、视图等
3.存储引擎 : 负责 MySQL 中的数据存储和提取,和 Linux 下的文件系统类似,每种存储引擎都有其优势和劣势,中间的服务层通过 API 与存储引擎通信,这些 API接口 屏蔽不同存储引擎间的差异

MySQL查询过程
在这里插入图片描述

MySQL 整个查询执行过程,总的来说分为 5 个步骤 :
1.客户端向 MySQL 服务器发送一条查询请求
2.服务器首先检查查询缓存,如果命中缓存,则立刻返回存储在缓存中的结果,否则进入下一阶段
3.服务器进行 SQL解析、预处理、再由优化器生成对应的执行计划
4.MySQL 根据执行计划,调用存储引擎的 API来执行查询
5.将结果返回给客户端,同时缓存查询结果.

客户端/服务端通信协议
1 在任一时刻,要么是服务器向客户端发送数据,要么是客户端向服务器发送数据,这两个动作不能同时发生。
2.一旦一端开始发送消息,另一端要接收完整个消息才能响应它,而不是心跳机制,MySQL客户端/服务端通信协议 是 “半双工” 的。
3. 无法也无须将一个消息切成小块独立发送,也没有办法进行流量控制

注意
4.客户端用一个单独的数据包将查询请求发送给服务器。
5.当查询语句很长的时候,需要设置 max_allowed_packet参数,如果查询实在是太大,服务端会拒绝接收更多数据并抛出异常。
6. 服务器响应给用户的数据通常会很多,由多个数据包组成。但是当服务器响应客户端请求时,客户端必须完整的接收整个返回结果,而不能简单的只取前面几条结果,然后让服务器停止发送。
7. 在实际开发中,尽量保持查询简单且只返回必需的数据,减小通信间数据包的大小和数量是一个非常好的习惯,这也是查询中尽量避免使用 SELECT *以及加上LIMIT限制的原因之一。

查询缓存
在解析一个查询语句前,如果查询缓存是打开的,那么 MySQL 会检查这个查询语句是否命中查询缓存中的数据。
两种情况:
1.如果当前查询恰好命中查询缓存,查询不会被解析,也不会生成执行划,更不会执行

2.如果缓存中没有要查询的数据集,则进入解析器解析,预处理器预处理,查询优化器优化生成执行计划,执行执行计划查询数据库存储引擎,调用存储引擎api接口,查询出数据后,把数据进行缓存,然后返回给客户端

注意
3.MySQL将缓存存放在一个引用表 (不要理解成table,可以认为是类似于 HashMap 的数据结构),通过一个哈希值索引(这个哈希值通过查询本身、当前要查询的数据库、客户端协议版本号等一些可能影响结果的信息计算得来),所以查询语句在任何字符上的不同 (例如 : 空格、注释),都会导致缓存不会命中

4. 如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、MySQL库中的系统表,其查询结果都不会被缓存

例如:
a.函数 NOW() 或者 CURRENT_DATE() 会因为不同的查询时间,返回不同的查询结果。

b.包含 CURRENT_USER 或者 CONNECION_ID() 的查询语句会因为不同的用户而返回不同的结果,将这样的查询结果缓存起来没有任何的意义

5. MySQL查询缓存系统会跟踪查询中涉及的每个表,如果这些表 (数据或结构) 发生变化,那么和这张表相关的所有缓存数据都将失效.

注意
6.在任何的写操作时,MySQL必须将对应表的所有缓存都设置为失效。

7. 如果查询缓存非常大或者碎片很多,这个操作就可能带来很大的系统消耗,甚至导致系统僵死一会儿,而且查询缓存对系统的额外消耗也不仅仅在写操作,读操作也不例外,也会带来消耗 :

a. 任何的查询语句在开始之前都必须经过检查,即使这条 SQL语句 永远不会命中缓存

b.如果查询结果可以被缓存,那么执行完成后,会将结果存入缓存,也会带来额外的系统消耗

在进行读操作时,查询缓存非常大或者碎片很多时
a查询前无论如何都会被检查带来额外的系统消耗。
b.查询进行时会带来消耗。
c.查询出来结果后,查询结果要被缓存也会带来额外的系统消耗。

8.并不是什么情况下查询缓存都会提高系统性能,缓存和失效都会带来额外消耗,特别是写密集型应用,只有当缓存带来的资源节约大于其本身消耗的资源时,才会给系统带来性能提升

9.查询缓存的一些操作

FLUSH QUERY CACHE //清理查询缓存内存碎片
RESET QUERY CACHE //从查询缓存中移出所有查询
FLUSH TABLES //关闭所有打开的表,同时该操作将会清空查询缓存中的内容

查询优化器
经过了解析器的解析以及预处理器的预处理,所生成的语法树应该是合格的了,现在该由优化器将其转化成查询计划。

1.多数情况下,一条查询可以有很多种执行方式,而优化器选择其中成本最小的一个作为最好的执行计划

2.优化器的作用就是找到这其中最好的执行计划。MySQL使用基于成本的优化器,它尝试预测一个查询使用某种执行计划时的成本,并选择其中成本最小的一个。

3. 在 MySQL 可以通过查询当前会话的 last_query_cost 的值来得到其计算当前查询的成本,
(数据比较少,将就吧)

SELECT * FROM menu WHERE id BETWEEN  1  AND  35 ;

SHOW STATUS LIKE 'last_query_cost';

在这里插入图片描述
在这里插入图片描述

4. 有非常多的原因会导致 MySQL 选择错误的执行计划,比如统计信息不准确、不会考虑不受其控制的操作成本(用户自定义函数、存储过程)、MySQL认为的最优跟我们想的不一样 (我们希望执行时间尽可能短,但 MySQL 值选择它认为成本小的,但成本小并不意味着执行时间短) 等等


5. MySQL的查询优化器是一个非常复杂的部件,它使用了非常多的优化策略来生成一个最优的执行计划。

查询执行引擎
在经过了解析器解析以及预处理器预处理所生成的语法树由优化器进行优化生成执行计划,查询执行引擎根据执行计划给出的指令逐步执行得出结果。

  1. 整个执行过程的大部分操作均是通过调用存储引擎实现的接口来完成,这些接口被称为 handler API。查询过程中的每一张表由一个 handler 实例表示。

  2. 实际上,MySQL在查询优化阶段就为每一张表创建了一个 handler实例,优化器可以根据这些实例的接口来获取表的相关信息,包括表的所有列名、索引统计信息等

注意
每张表对应的handler实例,是在优化器阶段就创建了的

  1. 存储引擎接口提供了非常丰富的功能,但其底层仅有几十个接口,这些接口像搭积木一样完成了一次查询的大部分操作

返回结果给客户端
在经过了客户端发送请求到MySQ服务器,检查查询缓存是否打开以及是否命中缓存,没命中则经过解析器解析,预处理器预处理,优化器优化生成执行计划,调用存储引擎的API来执行执行计划,最后将查询出来的结果返回给客户端。

  1. 即使查询不到数据,MySQL 仍然会返回这个查询的相关信息,比如该查询影响到的行数以及执行时间等。

  2. 如果查询缓存被打开且这个查询可以被缓存,MySQL也会将结果存放到缓存中。

  3. 结果集返回客户端是一个增量且逐步返回的过程。有可能 MySQL 在生成第一条结果时,就开始向客户端逐步返回结果集。这样服务端就无须存储太多结果而消耗过多内存,也可以让客户端第一时间获得返回结果。

注意
4.结果集中的每一行都会以一个满足客户端/服务器通信协议的数据包发送,再通过 TCP协议进行传输,在传输过程中,可能对 MySQL 的数据包进行缓存然后批量发送。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

偷偷学习被我发现

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值