MySQL-浅析查询SQL语句执行过程

过程概览

一.查询缓存

MySQL会用一张引用表,将查询缓存以Key-Value的方式进行缓存,Key是查询语句,Value则是查询语句的结果,并且通过一个哈希值来引用,此哈希值受查询语句整体、当前执行查询的数据库、甚至是客户端协议版本等影响。

在查询缓存阶段,首先会对执行语句的用户进行权限校验 ,有查询该表的权限的用户,才能继续进行。若上一次该查询语句缓存了结果,则可以直接返回结果给Client,直接省去解析、预处理、优化、执行的过程,能够提高数据库查询的性能。

但也正因为未进行解析、预处理,空格、注释(两条语句间任何 字符的不同)也会影响命中率,查询语句中包含了不确定的数据,也不会被缓存,如CURRENT_DATE()、自定义函数、临时表等,若表发生变化,查询缓存可能会失效,所以一般应用于多次使用、读取频繁且数据变化不频繁、数据量大的查询。

查询缓存默认是关闭的,若需要启用查询缓存,通过在服务器配置文件my.cnf 中添加query_cache_type=1或者query_cache_type=2,若等于2,则只对显示定义SQL_CACHE有效。

确定要执行的查询缓存,可以用SQL_CACHE显示指定:

csharp 复制代码
select SQL_CACHE column_name from table_name;

由于使用场景较少、可能导致并发性能问题,MySQL在8.0后版本移除了查询缓存。

二.解析器、预处理器

解析器是对查询语句通过词法分析(关键字)、语法解析(语法规则)来生成一个数据结构------解析树(select_lex),词法分析是将SQL语句拆成一个一个单词进行检查,而语法分析则顾名思义,检查语句是否符合SQL的语法规则,在此阶段,并不会对语句中的字段名、表名进行检查。

SQL语句若符合上述条件,则预处理器会进一步检查解析树是否合法,例如表、字段是否存在、命名、别名是否存在歧义,所以当语法错误和字段不匹配同时出现,会先报语法错误。

三.优化器

优化器会根据它认为的最优的执行计划执行,有多个索引,决定使用哪个索引,有多表关联,优先连接哪个表等。优化器会将传入的解析树生成一个/多个执行计划,执行计划的个数跟查询语句中的条件也有关系。生成执行计划会消耗较多时间,特别是当有多个执行计划的时候。

csharp 复制代码
select name from school where gender = 'Male'  and class = 9;

Plan A:先在school表中找出gender字段值为'Male'的行,再判断class字段值是否为9。

Plan B:先在school表中找出class字段值为9的行,再判断gender字段值是否为'Male'。

优化器分为两种:CBO基于代价的优化器、RBO基于规则的优化器,MySQL使用的是CBO

CBO会从多个执行路径中选择一个"成本"最小的执行路径来作为执行计划。成本的具体计算是非常复杂的,简单的说,成本代表了MySQL根据统计信息(如索引,表,行)通过成本模型计算出来目标SQL对应的步骤的IO,CPU等消耗,也就是说统计信息的大小、成本模型的合理性影响着执行计划的选择。

如果使用的是预编译SQL,则经过一次编译,就能够多次运行,省去解析、优化的过程。

如果此时存在执行计划缓存,就可以直接使用已缓存的执行计划,跳过生成执行计划,加快查询SQL的速度。

四.执行器

执行器根据传入的执行计划完成整个查询,但首先会检查用户是否拥有对该表的操作权限,再根据表的引擎定义调用引擎接口去根据执行计划对表进行查询。

如果不存在过滤,MySQL将进行全表扫描,返回所有行。

如果存在过滤,根据条件过滤(若存在索引,且开启了索引下推,则交由存储引擎完成),符合则存储在结果集中,不符合则跳过,如此遍历到最后。

当有一条结果生成,其实就在开始准备向Client返回数据了,一旦整个查询的结果集被完整获取并存储在缓存中,MySQL 会一次性将整个结果集返回给Client,所以看起来就像是一次性发送的。

五.存储引擎

MySQL5.6之后 新增了索引下推的功能:将执行器数据筛选的过程交由存储引擎 处理,减少了Server层(解析器预处理器、优化器、执行器)的负担,提高查询的效率,特别是在使用索引的时候,可以减少扫描的数据量,减少不必要的读取。

索引下推:在传统的查询流程中,MySQL通过索引检索符合条件的行,然后通过回表 操作获取实际的数据行。因为索引通常只存储了行的标识符(PRIMARY KEY/ID),而不是完整的行数据,所以才需要回表。而索引下推会将部分where子句中的条件下推到索引扫描过程中,在索引扫描的同时过滤,因为在索引扫描的时候还未读取整个行数据,且减少了回表的数量,所以特别是在大表和复杂查询中,能够显著提高查询的性能。

索引下推默认是开启的,也可以在系统变量中查看index_condition_pushdown的值是否为on。

sql 复制代码
show variables like 'optimizer_switch'\G;

参考文章链接:

sql执行流程概述_sql执行过程-CSDN博客

一条SQL语句在MySQL中执行过程全解析_本篇文章会分析下---个sql语句在mysql中的执行流程,包括sql的查询在mysql内部会怎-CSDN博客

MySQL进阶学习(一)----MySQL架构与SQL执行流程 - 掘金

MySQL探秘(二):SQL语句执行过程详解 - 掘金

MySQL教程2:从MySQL的逻辑架构看SQL查询语句是如何被执行的,了解连接管理、解析器、查询优化器、执行引擎,Server层和引擎层各自的作用 - 掘金

MySQL的SQL预处理(Prepared) - 海东潮 - 博客园

mysql之优化器、执行计划、简单优化 - 烟雨楼人 - 博客园

MySQL查询语句完整语法解析 - Hu.R - 博客园

相关推荐
Sunyanhui11 小时前
牛客网 SQL36查找后排序
数据库·sql·mysql
老王笔记1 小时前
MHA binlog server
数据库·mysql
2401_871213302 小时前
mysql高阶语句
数据库·mysql
山山而川粤4 小时前
网络安全宣传系统|Java|SSM|JSP|
java·开发语言·后端·学习·mysql
_汤姆大叔5 小时前
MySQL 高级操作全解析
数据库·mysql
呼啦啦啦啦啦啦啦啦6 小时前
【MySQL篇】聚合查询,联合查询
数据库·mysql
今天不coding7 小时前
MySQL体系架构
数据库·mysql·体系架构·网络连接层·服务层·存储引擎层·系统文件层
奥顺互联V9 小时前
一次性部署:使用Docker部署PHP应用
大数据·mysql·开源·php
小黄人软件9 小时前
20241220流水的日报 mysql的between可以用于字符串 sql 所有老日期的,保留最新日期
数据库·sql·mysql
无为之士10 小时前
Linux自动备份Mysql数据库
linux·数据库·mysql