大家好,我是冰河~~

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字段标识的行数并不完全相同。

好了,今天就到这儿吧,我是冰河,大家有啥问题可以在下方留言,也可以加我微信:sun_shine_lyz,我拉你进群,一起交流技术,一起进阶,一起牛逼~~

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

  1. 一文搞懂select语句在MySQL中的执行流程!

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

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

    来源:http://t.cn/E6U9Z9T 概览 本篇文章会分析下一个sql语句在mysql中的执行流程,包括sql的查询在mysql内部会怎么流转,sql语句的更新是怎么完成的. 一.mysql架 ...

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

    日常读书笔记

  4. mysql一秒查询次数_单个select语句实现MySQL查询统计次数

    单个select语句实现MySQL查询统计次数 单个select语句实现MySQL查询统计次数的方法用处在哪里呢?用处太多了,比如一个成绩单,你要查询及格得人数与不及格的人数,怎么一次查询出来? My ...

  5. 学习MySQL:使用SELECT语句从MySQL服务器查询数据

    In this series of articles, we are going to learn about the basics of the MySQL database server. In ...

  6. SQL语句在Mysql中是如何被执行的?

    前言 相信大家用了这么久的Mysql,一定很好奇自己写的SQL是如何执行并返回结果的,今天我们就来一层一层剥开Mysql这颗洋葱. 首先我们通过一张图来了解下整个过程,然后再开始一步一步解析. 第一步 ...

  7. 一条sql语句在mysql中如何执行的

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

  8. 别看是面试问烂的题目,一面试你照样还是不会系列MySQL四种隔离级别,看完吊打面试官!

    别看是面试问烂的题目,一面试你照样还是不会系列MySQL四种隔离级别,看完吊打面试官! 什么是事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消.也 ...

  9. mysql中select使用方法,MySQL中select语句介绍及使用示例

    数据表都已经创建起来了,假设我们已经插入了许多的数据,我们就可以用自己喜欢的方式对数据表里面的信息进行检索和显示了,比如说:可以象下面这样把整个数据表内的内容都显示出来 select * from p ...

最新文章

  1. [转]Extending the User Interface in Outlook 2010
  2. muduo之FileUtil
  3. 什么时候用抽象?什么时候用接口?
  4. 利用std::allocator实现自定义的vector类
  5. Linux 常见命令之Find \; +结合其它命令使用案例详解
  6. 循环队列解决约瑟夫问题
  7. 菜鸟学习笔记:Java提升篇5(IO流1——IO流的概念、字节流、字符流、缓冲流、转换流)
  8. iOS 14.5 目前已經發布了8 個測試版更新
  9. 前端 HTML 获取自定义标签tag 的值方法
  10. 洛谷——P1146 硬币翻转
  11. Redis教程:主从复制
  12. IE6/7 单选按钮 radio 无法选中解决方法
  13. elasticjob disable JOB
  14. 文本分析苏轼的词以及苏轼的人生轨迹地图
  15. 2021年最新独立版橙色去水印微信小程序-更新2021.8.31
  16. 你用过的每款APP都具有这一特点,但你却不知道……
  17. ps4变更账号服务器,PSN ID怎么改?详细步骤教你如何更改PS4的PSN ID
  18. 汉字转拼音的C++实现及原理_gb2312区位码篇
  19. php通用查询系统excel,Laravel+Excel通用查询填报系统
  20. Django模型之Meta属性详解

热门文章

  1. python无法安装pyqt5_关于python pyqt5安装失败问题的解决方法
  2. 使用CAD旋转复制命令绘制图形
  3. TCS3200的使用
  4. RFID防伪溯源系统
  5. 恶意软件及其类型(病毒、蠕虫、木马、间谍软件、勒索软件、恐吓软件、Bots和Rootkits等)的介绍
  6. Day3: FlipIt – Windows的开源翻页时钟
  7. 支持动图、一键生成,基于 React 的开源像素绘画应用 —— Pixel Art to CSS
  8. rust第三人称视角插件_一个第三人称游戏相机的实现(基于rust语言和cgmath库)...
  9. 华为云安全云脑,让企业云化运营更放心
  10. 用场景法剖析需求问题