SQL查询语句执行流程
msyql执行流程
你有个最简单的表,表里只有一个 ID 字段,在执行下面这个查询语句时::
select * from T where ID=10;
我们看到的只是输入一条语句,返回一个结果,却不知道这条语句在 MySQL 内部的执行过程。
下面我给出的是 MySQL 的基本架构示意图,从中你可以清楚地看到 SQL 语句在 MySQL 的各个功能模块中的执行过程。
大体上,MySQL 分为 Server 层和存储引擎层两部分。
Server 层包括连接器、查询缓存、分析器、执行器等,以及所有的内置函数(如日期、时间、数学和加密函数等)和跨存储引擎的功能(如存储过程、触发器、视图)。
存储引擎层负责数据的存储和提取,支持 InnoDB、MyISAM、Memory 等多个存储引擎。MySQL 5.5.5 版本后默认存储存储引擎是 InnoDB。
连接器
- 验证账号密码是否正确
- 到权限表里面查出你拥有的权限,之后的执行语句,都会依赖这个权限数据。
查询缓存
在建立连接后,就开始执行 select 语句了,执行前首先会查询缓存。
MySQL 拿到查询请求后,会先查询缓存,看是不是执行过这条语句。执行过的语句及其结果会以 key-value 对的形式保存在一定的内存区域中。key 是查询的语句,value 是查询的结果。如果你的查询能够直接在这个缓存中找到 key,那么这个value 就会被直接返回给客户端。
如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中。如果查询命中缓存,MySQL 不需要执行后面的复杂操作,就可以直接返回结果,会提升效率。
但是查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。对于更新压力大的数据库来说,查询缓存的命中率会非常低。如果业务中需要有一张静态表,很长时间才会更新一次。比如,一个系统配置表,那这张表上的查询才适合使用查询缓存。MySQL 提供了这种按需使用的方式。可以将参数 query_cache_type 设置成 DEMAND,对于默认的 SQL 语句都将不使用查询缓存。
MySQL 8.0 版本将查询缓存的功能删除了。
分析器
如果没有命中查询缓存,就要开始真正执行语句了。首先,MySQL 需要知道你要做什么,因此需要对 SQL 语句做解析。
分析器先会做“词法分析”。你输入的是由多个字符串和空格组成的一条 SQL 语句,MySQL 需要识别出里面的字符串分别是什么,代表什么。MySQL 从你输入的"select"这个关键字识别出来,这是一个查询语句。它也要把字符串“T”识别成“表名 T”,把字符串“ID”识别成“列 ID”。做完了这些识别以后,就要做“语法分析”。根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。
如果你的语句不对,就会收到“You have an error in your SQL syntax”的错误提醒,比如下面这个语句 select 少打了开头的字母“s”。
elect * from t where ID=1;
/*
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'elect * from t where ID=1' at line 1
*/
优化器
经过了分析器,MySQL 就知道你要做什么了。在开始执行之前,还要先经过优化器的处理。
优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。比如你执行下面这样的语句,这个语句是执行两个表的 join:
select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
- 既可以先从表 t1 里面取出 c=10 的记录的 ID 值,再根据 ID 值关联到表 t2,再判断 t2 里面 d 的值是否等于 20。
- 也可以先从表 t2 里面取出 d=20 的记录的 ID 值,再根据 ID 值关联到 t1,再判断 t1 里面 c 的值是否等于 10。
执行器
MySQL 通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句。
开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误,如下所示 (在工程实现上,如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证。查询也会在优化器之前调用 precheck 验证权限)。
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 并不是完全相同的。
总结
主要通过对一个 SQL 语句完整执行过程进行讲解,介绍 MySQL 的逻辑架构,MySQL 主要包括连接器、查询缓存、分析器、优化器、执行器这几个模块。
参考文章
SQL查询语句执行流程的更多相关文章
- MySQL基础架构之查询语句执行流程
这篇笔记主要记录mysql的基础架构,一条查询语句是如何执行的. 比如,在我们从student表中查询一个id=2的信息 select * from student where id=2; 在解释这条 ...
- SQL查询语句执行的逻辑顺序
一.简介 大家都知道SELECT语句是用来查询数据表中的数据的,构成SELECT语句的还有各种元素(where.from.group by等),不同元素又代表了不同的处理逻辑,那么这些元素在执行查询时 ...
- SQL查询语句执行速度快,存储过程执行慢
今天一个生成10w条数据的存储过程执行了95s,但是单独执行SQL语句只需要28s,查资料后发现原来这是存储过程的机制导致的,也就是传说中的参数嗅探 网上的一段话: (1)可能是发生了参数嗅探,第一次 ...
- SQL查询语句执行的顺序是-----------------
MSSQL逻辑查询的步骤 摘自:Microsoft SQL Server 2005技术内幕:T-SQL查询: 逻辑查询处理中的各个阶段 本节介绍逻辑查询处理所涉及的各个阶段.我先简要描述一下每个阶段, ...
- MySQL 笔记整理(2) --日志系统,一条SQL查询语句如何执行
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 2) --日志系统,一条SQL查询语句如何执行 MySQL可以恢复到半个月内任意一秒的状态,它的实现和日志系统有关.上一篇中记录了一 ...
- MySQL数据库详解(一)执行SQL查询语句时,其底层到底经历了什么?
一条SQL查询语句是如何执行的? 前言 大家好,我是WZY,今天我们学习下MySQL的基础框架,看一件事千万不要直接陷入细节里,你应该先鸟瞰其全貌,这样能够帮助你从高维度理解问题.同样,对于MyS ...
- 1 基础架构:一条sql查询语句如何执行?
1 基础架构:一条sql查询语句如何执行? 分析一个最简单的查询 mysql> select * from T where ID=10: MySQL基本架构示意图 大体来说,mysql可以分为s ...
- 一文读懂一条 SQL 查询语句是如何执行的
2001 年 MySQL 发布 3.23 版本,自此便开始获得广泛应用,随着不断地升级迭代,至今 MySQL 已经走过了 20 个年头. 为了充分发挥 MySQL 的性能并顺利地使用,就必须正确理解其 ...
- oracle中sql查询语句的执行顺序
查询语句的处理过程主要包含3个阶段:编译.执行.提取数据(sql查询语句的处理主要是由用户进程和服务器进程完成的,其他进程辅助配合) 一.编译parse 在进行编译时服务器进程会将sql语句的正文放入 ...
随机推荐
- 虚拟机安装的kali操作系统实现共享文件夹
虚拟机共享文件夹设置. 1.[虚拟机]-->[设置] 2.先在本地新建一个共享文件夹,然后将此文件夹的路径添加到虚拟机 3.进入kali操作系统,运行命令sudo vmhgfs-fuse .ho ...
- QLabel的使用
现在学习一个简单的控件Label. 第一步:打开designer.exe.拖动一个控件到主窗口,双击可以编辑文字. 第二步:设置字体大小 第三步:设置文字颜色 第四步:设置背景色 第五步:将文字居中 ...
- 第十二篇 -- 关于U盘制作启动盘后在本机上显示不出来的解决方案
喜欢玩电脑的朋友应该都重装过系统,最常用的就是用U盘装系统.以前装系统都没问题,不过偶然一次发现了一个问题,就是那个被制作成启动盘的U盘,插在本机上只能显示EFI启动文件部分,而其他空间全都显示不出来 ...
- 素数(质数)(Java版)
4.输出质数(素数) 素数(质数):是指在大于1的自然数中,除了1和它本身外,不能被其他自然数整除(除0以外)的数 public class PrimeNumber { public static v ...
- Python开发篇——如何在Flask下编写JWT登录
首先,HTTP 是无状态的协议(对于事务处理没有记忆能力,每次客户端和服务端会话完成时,服务端不会保存任何会话信息)--每个请求都是完全独立的,服务端无法确认当前访问者的身份信息,无法分辨上一次的请求 ...
- tomcat与springmvc 结合 之---第16篇 servlet如何解析成员变量和DispatcherServlet如何解析
writedby 张艳涛,用了两个星期将深入刨析tomcat看完了,那么接下来该看什么呢?真是不知道,知识这东西上一个月看的jvm,锁.多线程并发 又都忘了.... tomcat学完,我打算看spri ...
- anyRTC视频连麦demo上线啦!
音频连麦demo一经问世就得到开发者的一致好评,有很多开发者咨询视频连麦的demo该怎么去实现,本着让"视频交付更简单"的理念,我们推出了视频连麦demo! 音视频技术不仅局限用于 ...
- 小技巧 | Get 到一个 Web 自动化方案,绝了!
1. 前言 大家好,我是安果! 无论是 Chrome,还是 Firefox 浏览器,它们的强大性在很大程度上都是依赖于海量的插件,让我们能高效办公 那我们是否可以编写一个插件,让浏览器自动化完成一些日 ...
- windows的自动登录和隐藏用户
Launch Regedit. #r -> regedit 1. Navigate to: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\Cu ...
- CTFre-getit-WP
攻防世界getit-WP 日子忙起来人也就忙,CTF慢慢刷,慢就是快. 下载之后,也没管别的直接就IDA打开:下载之后,也没管别的直接就IDA打开: 随便点点看得到三个可以字符串.F5看看: 懂个大概 ...