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 - 博客园

相关推荐
程序猿小D1 分钟前
[附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+jsp实现的电影小说网站管理系统,推荐!
java·数据库·mysql·spring·毕业设计·ssm框架·电影小说网站
羊小猪~~7 分钟前
数据库学习笔记(十七)--触发器的使用
数据库·人工智能·后端·sql·深度学习·mysql·考研
叁沐1 小时前
MySQL 05 深入浅出索引(下)
mysql
陈卓4102 小时前
MySQL-主从复制&分库分表
android·mysql·adb
你都会上树?2 小时前
MySQL MVCC 详解
数据库·mysql
长征coder3 小时前
AWS MySQL 读写分离配置指南
mysql·云计算·aws
ladymorgana4 小时前
【docker】修改 MySQL 密码后 Navicat 仍能用原密码连接
mysql·adb·docker
PanZonghui4 小时前
Centos项目部署之安装数据库MySQL8
linux·后端·mysql
GreatSQL社区4 小时前
用systemd管理GreatSQL服务详解
数据库·mysql·greatsql
掘根4 小时前
【MySQL进阶】错误日志,二进制日志,mysql系统库
数据库·mysql