大家好,我是冰河~~

MySQL作为互联网行业使用最多的关系型数据库之一,与其免费、开源的特性是密不可分的。然而,很多小伙伴工作了很多年,只知道使用MySQL进行CRUD操作,这也导致很多小伙伴工作多年后,想跳槽进入大厂,却在面试的时候屡屡碰壁。

问个简单的问题:select语句是如何在MySQL中执行的? 这也是很多面试官喜欢问的问题,如果你连这个简单的问题都不能回答的话,那就要好好规划下自己的职业生涯了。

好了,今天我们就一起来聊聊select语句是如何在MySQL中执行的。文章的主要内容如下。

频繁使用的select语句

为了更好地贯穿全文,这里先来列举一个最简单的select查询语句,例如:查询user表中id为1001的用户信息,使用下面的SQL语句进行查询。

select * from user where user_id = 1001;

当我们在MySQL的命令行中输入上述SQL语句时,这条SQL语句到底在MySQL中是如何执行的呢?接下来,我们就以这条SQL语句为例,说说select语句是如何在MySQL中执行的。

MySQL逻辑架构

在介绍select语句在MySQL中的执行流程之前,我们先来看看MySQL的逻辑架构,因为任何SQL语句的执行都离不开MySQL逻辑架构的支撑。也就是说,SQL语句在MySQL中的执行流程与MySQL的逻辑架构是密不可分的。

在上图中,我们简单的画了下MySQL的逻辑架构图,并且给出了逻辑分层和每层中各部分的功能。从逻辑上,我们可以将MySQL粗略地分成三层:Server层、存储引擎层和系统文件层,而Server层中又可以分成网络连接层(连接器)和数据服务层(Server层)。

Server层中包含了连接器、查询缓存、分析器、优化器和执行器等MySQL的核心组成部分,另外,在Server层中还包含了所有的内置函数(比如:日期时间函数、加解密函数、聚合函数、数学函数等),存储引擎、触发器、视图等等。

存储引擎层主要负责和系统文件层进行交互,存储引擎层本身是插件式的架构设计,支持InnoDB、MyISAM、Archive、Memory等存储引擎。在MySQL 5.5.5及以后的版本中,MySQL的默认存储引擎是InnoDB。

系统文件层主要负责存储实际的数据,将数据以文件的形式存储到服务器的磁盘上。

接下来,我们就来说说一条select语句在MySQL的逻辑架构的每一部分到底是如何执行的。

连接器是如何授权的?

首先,我们先来看看在服务器命令行输入连接MySQL的命令时,MySQL的连接器是如何进行验证的。比如,我们在服务器的命令行输入了如下命令。

mysql -ubinghe -p

执行“回车”后,输入binghe账户的密码,与MySQL进行连接。此时,连接的过程需要完成经典的TCP握手操作(有关TCP的握手相关的知识,小伙伴们可以参考《【面经】面试官:讲讲七层网络模型与TCP三次握手与四次断开?》)。之后,连接器就开始认证连接的身份是否合法,最直接的就是验证用户名和密码是否正确。

如果用户名或者密码错误,MySQL会提示 Access denied for user 。如果用户名和密码正确,则连接器会到MySQL的权限表中查询当前连接拥有的权限。查询到权限之后,只要这个连接没有断开,则这个连接涉及到的权限操作都会依赖此时查询到的权限。

换句话说,一个用户登录MySQL并成功连接MySQL后,哪怕是管理员对当前用户的权限进行了修改操作,此时只要这个用户没有断开MySQL的连接,就不会受到管理修改权限的影响。管理员修改权限后,只有对新建的连接起作用。

如果客户端连接MySQL后,长时间没有执行任何操作,则连接器会自动断开与这个客户端的连接。具体多长时间断开是由MySQL的参数wait_timeout控制的,这个值默认是8小时。我们可以根据实际业务需要,自行调整这个参数的值,以使MySQL能够满足我们的实际业务场景。

由于客户端与MySQL的连接是比较复杂的,这个过程也是比较耗时的,它会涉及TCP的握手操作,还会查询当前连接的权限信息等。往往在实际的工作过程中,我们会使用数据库连接池的方式,将数据库的连接缓存起来,这就意味着我们是使用长连接与MySQL进行交互的。

但是使用长连接连接MySQL也会有一个问题:那就是有时候会发现MySQL占用的内存涨得特别快,这是因为MySQL在执行的过程中,使用的临时内存是在连接对象里面进行管理的。这些占用的资源只有在连接断开的时候,才会被释放。如果连接长时间不释放,就会出现大量的临时内存占用内存空间。如果时间久了,可能会导致占用过多的内存,从而被操作系统“消灭”了,给人的感觉就是MySQL意外重启了。

我们可以使用如下的方案来解决这个问题:

  • 定期或者执行过一个比较占内存的查询操作后,断开连接,以后再重新建立和MySQL的连接。
  • 如果使用MySQL 5.7或更新的MySQL版本,可以通过执行mysql_reset_connection重新初始化MySQL的资源。重新初始化的过程不会重新连接MySQL,也不会重新做权限的验证操作。

查询缓存的作用是什么?

登录MySQL后,客户端就会与MySQL建立连接,此时执行select语句时,首先会到查询缓存中查询是否执行过当前select语句。如果之前执行过相应的select语句,则执行过的select语句和查询结果会以key-value的形式存放在查询缓存中,其中,key是查询语句,value是查询的结果数据。

如果在查询缓存中没有找到相应的数据,则会继续执行后续的查询阶段。执行完成后,会将结果缓存到查询缓存中。后续的查询如果命中缓存,则直接返回查询缓存中的数据,性能还是挺高的。

但是,大多数时候我不太建议小伙伴们开启查询缓存,为啥?原因很简单:查询缓存失效的频率是非常频繁的,只要对一个表进行更新操作,则这张表上所有的查询缓存都会被清空。 而且在MySQL 8.0中,直接删除了查询缓存的功能(冰河在看MySQL源码时,也证明了这一点)。

分析器对select语句做了什么?

分析器主要是对select语句进行 词法分析和语法分析 操作。

如果select语句没有命中缓存,则首先会由分析器对其进行“词法分析”操作,此时,MySQL会识别select语句中的每个字符串代表什么含义。

例如,MySQL会通过"select"关键字识别出这是一个查询语句,也会把"user"识别为"数据表名user",把"id"识别成"字段名id"。接下来,就要进行“语法分析了”,根据语法规则,判断select语句是否满足MySQL的语法。如果判断出输入的SQL语句不满足语法规则,则MySQL会提示相应的错误信息。

优化器是如何优化select语句的?

对select语句进行了词法分析和语法分析后,还要经过优化器的优化处理才能执行。比如,我们的select语句中如果使用了多个索引,则优化器会决定使用哪个索引来查询数据;再比如,在select语句中,有多表关联的操作,优化器会决定各表的连接顺序,数据表的连接顺序不同,对于执行的效率会大不相同,优化器往往会选择使用查询效率高的连接顺序。

如果select语句经过优化器的优化之后,就会进入执行阶段了。

执行器如何执行select语句?

进入执行阶段的select语句,首先,执行器会对当前连接进行权限检查,最直接的方式就是检查当前连接是否对数据表user具有查询权限。如果当前连接对数据表user没有查询权限,就会返回没有权限的错误。例如,会返回如下错误。

ERROR 1142 (42000): SELECT command denied to user 'binghe'@'localhost' for table 'user'

如果当前连接具有对数据表user的查询权限,则会继续执行。首先会进行打开数据表的操作,此时优化器会根据创建表时使用的存储引擎,使用相应存储引擎的接口执行查询操作。这里,我们举一个例子:

假设,我们在id字段上没有建立索引,执行器执行的流程大致如下所示。

(1)通过存储引擎读取数据表user的第一行数据,判断当前行的id值是否等于1001,如果不等于1001,则继续读取下一行数据;如果等于1001,则将当前行放入结果集中。

(2)继续通过存储引擎读取下一行数据,执行与(1)相同的逻辑判断,直到处理完user表中的所有数据。

(3)处理完所有的数据后,执行器就会将结果集中的数据返回给客户端。

如果在id字段上有索引的话,执行的整体逻辑与id字段上没有索引大体一致。

如果开启了慢查询的话,执行select语句时,会在慢查询日志中输出一个rows_examined字段,这个字段表示select语句在执行的过程中扫描了数据表中的多少行数据。不过在有些场景下,执行器调用一次,存储引擎内部会会扫描多行,这就导致存储引擎扫描的行数与rows_examined字段标识的行数并不完全相同。

好了,今天就到这儿吧,我是冰河,我们下期见~~

原来select语句在MySQL中是这样执行的!看完又涨见识了!这回我要碾压面试官!的更多相关文章

  1. 一条SQL语句在MySQL中是如何执行的

    概览 本篇文章会分析下一个sql语句在mysql中的执行流程,包括sql的查询在mysql内部会怎么流转,sql语句的更新是怎么完成的. 一.mysql架构分析 mysql主要分为Server层和存储 ...

  2. 一条查询语句在MySQL中是如何执行的?

    前言 我们在学习一种技术的时候,首先要鸟瞰其全貌,千万不要一开始就陷入到细节中去,这样有助于我们站在高维度其理解问题 —— 丁奇. 学习MySQL也是一样,所以我们可以从一条查询语句的执行开始看起. ...

  3. 一条SQL语句在MySQL中如何执行的

    本篇文章会分析一个 sql 语句在 MySQL 中的执行流程,包括 sql 的查询在 MySQL 内部会怎么流转,sql 语句的更新是怎么完成的. 在分析之前我会先带着你看看 MySQL 的基础架构, ...

  4. 一条 SQL 语句在 MySQL 中如何执行的

    一 MySQL 基础架构分析 1.1 MySQL 基本架构概览 下图是 MySQL 的一个简要架构图,从下图你可以很清晰的看到用户的 SQL 语句在 MySQL 内部是如何执行的. 先简单介绍一下下图 ...

  5. 原来一条select语句在MySQL是这样执行的《死磕MySQL系列 一》

    前言 看到蒋老师的第一篇文章后就收货颇丰,真是句句戳中痛点. 令我记忆最深的就是为什么知道了一个个技术点,却还是用不好 ?不管是蒋老师所说的Redis还是本系列要展开学习的MySQL. 这是一个值得思 ...

  6. 用sql的select语句从数据库中获取数据

    基本的select语句 select语句中的算数表达式和NULL值 列的别名 使用连接符操作,literal character strings,alternative quote operator, ...

  7. 使用PowerDesigner创建物理模型并生成SQL语句在MySQL中生成表

    我使用的PowerDesigner的版本为16.5,创建物理模型后,使用PowerDesigner生成的SQL语句,在MySQL中创建表. 1. 打开Power Designer软件,在弹出的欢迎对话 ...

  8. mysql 中sql的执行顺序

    文章转自 https://www.cnblogs.com/annsshadow/p/5037667.html https://www.cnblogs.com/yyjie/p/7788428.html ...

  9. 100道MySQL常见面试题总结,看完直接收藏

    前言 本文主要受众为开发人员,所以不涉及到MySQL的服务部署等操作,且内容较多,大家准备好耐心和瓜子矿泉水. 前一阵系统的学习了一下MySQL,也有一些实际操作经验,偶然看到一篇和MySQL相关的面 ...

随机推荐

  1. NOIP模拟测试14「旋转子段·走格子·柱状图」

    旋转子段 连60分都没想,考试一直肝t3,t2,没想到t1最简单 我一直以为t1很难,看了题解发现也就那样 题解 性质1 一个包含a[i]旋转区间值域范围最多为min(a[i],i)----max(a ...

  2. 为什么excel里面有的数据用CTRL+F,搜索搜不到?

  3. 如何利用Python计算景观指数AI

    可使用工具包 pylandstats 此工具包基本是根据fragstats形成的,大部分fragstats里面的景观指数,这里都可以计算.但是,还是有一小部分指数这里没有涉及. LS_METRICS ...

  4. Unity使用Photon PUN2设置中国区服务器

    原文地址:Unity使用Photon PUN2设置中国区服务器 入门系列 PUN2选择中国区服务器 先搜索中国区官网 选择试用购买 绑定你的Appid 注意: 当你的Appid申请了中国区后,海外的你 ...

  5. Pandas高级教程之:统计方法

    目录 简介 变动百分百 Covariance协方差 Correlation相关系数 rank等级 简介 数据分析中经常会用到很多统计类的方法,本文将会介绍Pandas中使用到的统计方法. 变动百分百 ...

  6. Spring:Spring注解大全

    @Controller 标识一个该类是Spring MVC controller处理器,用来创建处理http请求的对象. @Controller public class TestController ...

  7. Linux导出未越狱Iphone10.3-QQ聊天记录

    起因 手机当中的聊天记录已经快两年没有备份了,生怕某天QQ版本升级中丢失掉这些聊天记录,所想将这两年的聊天记录保存下来 查找了好多资料,结果10.3以后,IOS改变了策略,貌似不允许通过以前方法导出了 ...

  8. 排序---python版

    冒泡排序: 比较相邻的元素.如果第一个比第二个大,就交换它们两个: 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数: 针对所有的元素重复以上的步骤,除了最 ...

  9. MySQL存储引擎——InnoDB和MyISAM的区别

    MySQL5.5后,默认存储引擎是InnoDB,5.5之前默认是MyISAM. InnoDB(事务性数据库引擎)和MyISAM的区别补充: InnoDB是聚集索引,数据结构是B+树,叶子节点存K-V, ...

  10. 如何为HttpServer服务器配置PHP FastCGI,从而让HttpServer具备动态交互能力

    一.软件准备 1.下载HttpServer :HttpServer.zip HttpServer是一款windows平台下基于IOCP模型的轻量级.高并发.高性能web服务器(参见文章). 2.下载W ...