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

相关推荐
夜泉_ly7 分钟前
MySQL -安装与初识
数据库·mysql
月光水岸New3 小时前
Ubuntu 中建的mysql数据库使用Navicat for MySQL连接不上
数据库·mysql·ubuntu
我爱松子鱼4 小时前
mysql之规则优化器RBO
数据库·mysql
人间打气筒(Ada)5 小时前
MySQL主从架构
服务器·数据库·mysql
和道一文字yyds6 小时前
MySQL 中的索引数量是否越多越好?为什么?如何使用 MySQL 的 EXPLAIN 语句进行查询分析?MySQL 中如何进行 SQL 调优?
数据库·sql·mysql
哆木8 小时前
排查生产sql查询缓慢
数据库·sql·mysql
book01219 小时前
MySql数据库运维学习笔记
运维·数据库·mysql
纠结哥_Shrek10 小时前
Oracle和Mysql的区别
数据库·mysql·oracle
极客先躯10 小时前
说说高级java每日一道面试题-2025年2月13日-数据库篇-请说说 MySQL 数据库的锁 ?
java·数据库·mysql·数据库的锁·模式分·粒度分·属性分
我爱松子鱼11 小时前
MySQL 单表访问方法详解
数据库·mysql