首页 > 数据库 >【MySQL】简单解析一条SQL查询语句的执行过程

【MySQL】简单解析一条SQL查询语句的执行过程

时间:2025-01-14 23:32:12浏览次数:3  
标签:语句 缓存 SQL 查询 MySQL ID 连接

1. MySQL 的逻辑架构图

在这里插入图片描述

  • MySQL 架构主要分为 Server 层和存储引擎层。
  • Server 层集成了连接器、查询缓存、分析器、优化器和执行器等核心组件,负责提供诸如日期、时间、数学和加密等内置函数,以及实现存储过程、触发器、视图等跨存储引擎的功能。
  • 存储引擎层则负责数据的实际存储与提取,采用插件式设计,支持 InnoDB、MyISAM、Memory 等多种引擎,其中 InnoDB 自 MySQL 5.5.5 版本起成为默认存储引擎。

2. SQL 查询语句执行详解

2.1. 连接器:建立连接的关键环节

客户端通过如下命令发起数据库连接请求。

mysql -h$ip -P$port -u$user -p

完成 TCP 握手后,连接器依据输入的用户名和密码进行身份验证。

若用户名或密码错误,系统会立即返回 “Access denied for user” 错误,连接随即终止。若认证成功,连接器会从权限表中检索该用户的权限信息,并在后续该连接的操作中以此为依据进行权限判定。即便管理员在用户建立连接后修改了其权限,已有的连接权限也不受影响,新权限仅对新建立的连接生效。

连接成功后,若客户端长时间无操作,此连接便进入空闲状态,可使用 show processlist 命令查看,其中 Command 列为 “Sleep” 的记录即表示空闲连接。

在这里插入图片描述

若空闲时长超过 wait_timeout(默认 8 小时),连接器会自动断开连接。此时若客户端再次发送请求,会收到 “Lost connection to MySQL server during query” 错误提示,需重新连接并执行操作。

在实际应用场景中,由于建立连接的过程相对复杂,会消耗一定资源,因此建议尽量减少连接的建立次数,优先采用长连接。但长连接可能引发内存问题,因为 MySQL 在执行过程中临时使用的内存由连接对象管理,若连接持续不关闭,这些内存资源无法释放,可能导致内存占用过高,甚至引发系统强制终止 MySQL 进程(OOM),表现为 MySQL 异常重启。

解决此问题有两种途径:一是定期主动断开长连接,比如在程序中判断执行过一个占用大量内存的查询操作后断开连接;二是在 MySQL 5.7 及以上版本,可利用 mysql_reset_connection 命令重新初始化连接资源,此操作无需重新连接和权限验证,就能使连接恢复到初始创建时的状态。

2.2. 查询缓存:双刃剑般的存在

查询缓存的设计初衷是存储已执行过的 SQL 查询语句及其结果,以键值对(key-value)形式存在,其中查询语句为键,查询结果为值。当 MySQL 接收到查询请求时,会首先在查询缓存中查找是否存在相同的查询语句。例如,对于查询语句 select * from T where ID=10,若之前执行过且结果已缓存,系统会直接返回缓存中的结果,显著提升查询效率。

然而,查询缓存存在明显的局限性。只要对某个表进行更新操作,该表相关的所有查询缓存都会被清空。在实际业务中,如电商订单管理系统,数据表频繁更新,查询缓存的命中率极低。因此,在大多数情况下,不建议启用查询缓存

可通过将 query_cache_type 设置为 DEMAND 来禁用默认的查询缓存,对于确实需要缓存的特定查询,可使用 SQL_CACHE 进行显式指定。例如 mysql> select SQL_CACHE * from T where ID=10

值得注意的是,自 MySQL 8.0 版本起,已彻底移除查询缓存功能。

2.3. 分析器:语法语义的把关者

若查询未命中缓存,便进入分析器阶段。

首先进行词法分析,分析器会将输入的 SQL 语句(由多个字符串和空格组成)分解识别。以 select * from T where ID=10 为例,分析器能够识别出 “select” 为查询关键字,“T” 是表名,“ID” 是列名。

完成词法分析后,紧接着进行语法分析,依据语法规则检查语句的合法性。比如,若语句 elect * from t where ID=1(少打了开头的字母 “s”),分析器会提示 “You have an error in your SQL syntax” 错误,并准确指出错误位置在 “use near” 后的内容。

对于表中不存在的列引发的错误,也是在分析器阶段被检测到。例如执行 select * from T where k=1,若表 T 中不存在字段 k,分析器在语法分析过程中检查列的有效性时,会报出 “Unknown column ‘k’ in ‘where clause’” 错误。

2.4. 优化器:效率提升的幕后推手

经过分析器确定查询意图后,优化器开始发挥作用。

当表存在多个索引或语句涉及多表关联(join)时,优化器的重要性尤为凸显。

例如,对于查询语句 mysql> select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20,优化器需要权衡是先从表 t1 中取出 c = 10 的记录的 ID 值,再关联到表 t2 判断 d 的值是否为 20;还是先从表 t2 中取出 d = 20 的记录的 ID 值,再关联到表 t1 判断 c 的值是否为 10。

这两种执行路径虽然逻辑结果一致,但执行效率可能存在较大差异,优化器的核心任务就是选择最优的执行方案,确定后将执行计划传递给执行器。

2.5. 执行器:数据查询的执行者

执行器首先检查用户是否具有对查询表的执行权限。例如,执行 mysql> select * from T where ID=10,若用户没有相应权限,会返回 “ERROR 1142 (42000): SELECT command denied to user ‘b’@‘localhost’ for table ‘T’” 错误。若用户有权限,则根据表的引擎定义调用相应引擎接口执行查询。

以表 T 中 ID 字段无索引为例,执行器首先调用 InnoDB 引擎接口获取表的第一行数据,判断该行的 ID 值是否为 10,若不是则跳过该行,若是则将该行存入结果集。

接着继续调用引擎接口获取 “下一行” 数据,并重复上述判断逻辑,直至遍历完表的所有行。最后,执行器将满足条件的行组成的记录集返回给客户端。

在数据库的慢查询日志中,rows_examined 字段记录了执行器调用引擎获取数据行的累加次数,反映了语句执行过程中的扫描行数。

但需注意,在某些情况下,执行器调用一次引擎接口,在引擎内部可能扫描了多行,所以引擎扫描行数与 rows_examined 并不一定完全相同。

3. 示例解析

3.1. 案例说明

假设有一个名为 employees 的表,包含 idnameagedepartment 等字段,其中 id 为主键且有索引,department 字段也有索引。执行查询语句 select * from employees where department = 'IT' and age > 30

3.2. 执行流程拆解

首先,连接器验证客户端连接请求,确认用户有权限访问数据库和 employees 表。

接着,查询缓存检查是否存在该查询的缓存结果,若不存在则进入分析器阶段。分析器识别出关键字、表名和列名,并检查语法和语义,确保语句合法且列存在。

然后,优化器根据索引情况和数据分布决定执行计划。由于 departmentage 都有索引,优化器会评估先根据 department 索引筛选出 IT 部门的记录,再对这些记录检查 age 是否大于 30 更高效,还是反之更优,最终确定最佳执行路径。

最后,执行器按照优化器确定的计划调用存储引擎接口。例如,如果选择先按 department 索引查找,执行器会通过引擎接口获取满足 department = 'IT' 的第一行数据,检查 age 是否大于 30,符合条件则存入结果集,然后继续获取下一行数据重复判断,直至遍历完所有符合 department = 'IT' 条件的记录。最终将结果集返回给客户端。

标签:语句,缓存,SQL,查询,MySQL,ID,连接
From: https://blog.csdn.net/purplesky95/article/details/145149690

相关文章

  • MYSQL学习笔记(一):准备数据和数据库的最基本命令
    前言:学习和使用数据库可以说是程序员必须具备能力,这里将更新关于MYSQL的使用讲解,大概应该会更新30篇+,涵盖入门、进阶、高级(一些原理分析);这一篇是入门准备数据和一些关于数据库的操作命令;虽然MYSQL命令很多,但是自己去多敲一点,到后面忘记了,查一下就可以回忆起来使用了;这......
  • pyqt+mysql实现学生学籍管理系统(带.sql和.ui文件)
    所有文件已经上传至https://github.com/shuimqy/Student-Information-Management-System-implemented-with-Qt.git需要的话可自行下载,自己写的数据库大作业,尽量不要照搬提交。如果对你有帮助的话,点个赞吧,有问题欢迎留言!下面是我的涉及过程即设计报告。需求分析概念结构......
  • 【Java开发】Java、Maven、gradle、SQL、Redis常用命令大全:java程序员必备神器
    在Java开发的世界中,掌握Java、Maven、Gradle、SQL、Redis的常用命令是每个程序员的必修课。无论是构建项目、管理依赖,还是操作数据库,这些工具都能让你的开发效率提升一个档次!本文将为你整理一份超实用的命令清单,助你成为开发高手!一、Java:核心开发语言......
  • MySQL基础 数据库表的增删改
    Mysql数加科技整理一、原理定义概念定义数据库(Database)是按照数据结构来组织、存储和管理数据的建立在计算机存储设备上的仓库。数据库是长期储存在计算机内、有组织的、可共享的数据集合。分类:​ 非结构化数据:​ 数据相对来讲没有固定的特点,这种数据非常不便于检索......
  • MySQL基础函数使用
    DQL中的函数#官方函数链接https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format4.1 单行函数函数都是数据库提前给我们准备好的,所以我们可以直接调用,使用函数可以让指定的列计算出我们需要的数据单行函数:指的是操作一行数据返......
  • 用于与多个数据库聊天的智能 SQL 代理问答和 RAG 系统(4) —— 利用大型语言模型(LLM)生成
    实现一个与旅行相关的SQL数据库交互的工具,利用大型语言模型(LLM)生成和执行SQL查询,并通过语言模型处理查询结果生成最终答案。完整代码:fromlangchain_core.toolsimporttoolfromlangchain_community.utilitiesimportSQLDatabasefromlangchain.chainsimportcreate_......
  • 【转】SQL Server 时间日期 格式转换
    在SQLSERVER中,用CONVERT对日期作格式转换SELECTGETDATE()输出2025-07-0504:27:47 语句及查询结果:SelectCONVERT(varchar(100),GETDATE(),0):0516200610:57AMSelectCONVERT(varchar(100),GETDATE(),1):05/16/06SelectCONVERT(varchar(100),GETDATE()......
  • Mysql 高可用(MHA)-读写分离(Atlas)
    1.搭建主从复制(一主两从)1.1准备环境1主库:10.0.0.51/db012从库:10.0.0.52/db02,10.0.0.53/db031.2 清理环境1systemctlstopmysqld2rm-rf/data/mysql_3306/*3rm-rf/binlog/4mkdir/binlog/56创建相关目录与授权7主库操作:开启binlog和G......
  • 【转】[SQL Server] SSMS 中 SQL 语句的红色和蓝色关键字
     转自:Kimi.ai在SQLServerManagementStudio(SSMS)中,红色和蓝色关键字在SQL语句中的含义如下:蓝色关键字蓝色通常用于表示SQL语句中的关键字。这些关键字是SQL语言的核心部分,定义了SQL语句的功能和操作。常见的蓝色关键字包括:SELECTINSERTUPDATEDELETEFROMWHEREGROUPBY......
  • mysqlworkbench导入csv文件方法2(代码版)
    方法二:缺点--需要写代码,步骤稍多;优点--数据几秒内就可导完,以下是我实际工作场景步骤一:建表:步骤二:查看本地文件导入权限目录步骤三:将csv文件移到C:/ProgramData/MySQL/MySQLServer8.0/Uploads/此目录,并转为utf8,cmd可实现powershell-Command"(Get-Content-Path'D:/工......