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. 原来select语句在MySQL中是这样执行的!看完又涨见识了!这回我要碾压面试官!

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

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

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

  3. mysql执行一条sql语句的完整过程,sql语句在mysql中的执行过程

    文章目录 1. SQL语句在mysql的执行过程 一:客户端层 二:mysql服务器层 三:innoDB引擎层 2. undo日志.redo日志.binlog日志的区别? 1. SQL语句在mysql ...

  4. 一条 Select 语句 在 Postgresql 中的执行链路

    本文只是逻辑上的概览,并没有太过深入的设计细节的描述,对应的postgresql 的代码版本是 REL_12_2 1. DML 语句入口 如何搭建 gdb 调试pg 源代码环境,可以参考:利用GDB ...

  5. 一文搞懂交叉熵在机器学习中的使用,透彻理解交叉熵背后的直觉

    关于交叉熵在loss函数中使用的理解 交叉熵(cross entropy)是深度学习中常用的一个概念,一般用来求目标与预测值之间的差距.以前做一些分类问题的时候,没有过多的注意,直接调用现成的库,用起 ...

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

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

  7. 一文搞懂MySQL数据库分库分表

    如果数据量过大,大家一般会分库分表.分库需要注意的内容比较少,但分表需要注意的内容就多了. 工作这几年没遇过数据量特别大的业务,那些过亿的数据,因为索引设置合理,单表性能没有影响,所以实战中一直没用过 ...

  8. 一文搞懂 MySQL 索引

    一文搞懂 MySQL 索引 1.MySQL 索引 简介 1.1.MySQL 索引 是什么?  索引是一个单独的.存储在 磁盘 上的 数据库结构 ,包含着对数据表里 所有记录的 引用指针. 1.2. M ...

  9. 一文搞懂MySQL XA如何实现分布式事务

    一文搞懂MySQL XA如何实现分布式事务 前言 XA 协议 如何通过MySQL XA实现分布式事务 前言 MySQL支持单机事务的良好表现毋庸置疑,那么在分布式系统中,涉及多个节点,MySQL又是如 ...

最新文章

  1. 在 Shell 脚本里使用数组
  2. 王者争雄服务器维护,王者争雄_王者争雄官网_攻略-第一手游网
  3. 监测SQLServer数据库中表的数据变化 方案
  4. 马克.扎克伯格的执行力
  5. OpenYurt 单元化部署新增 Patch 特性
  6. mysql安装教程8.0.22_mysql 8.0.22 安装配置方法图文教程
  7. Effective C++ 第二版 1)const和inline 2)iostream
  8. postgresql 插入 时间戳_数据也玩躲猫猫?PostgreSQL中别人提交的数据,我为什么看不到?...
  9. 信息学奥赛一本通(1411:区间内的真素数)
  10. 什么是网络爬虫python_什么的什可以组什么词语
  11. SAP自学指南:案例公司的需求分析
  12. 实现1-2+3-4+5-6+…+99-100的算法的程序
  13. 如何快速搭建在线教育知识付费系统(附带源码)
  14. 解决 Hbuilder打包 Apk pad 无法横屏 以及 H5 直接打包 成Apk
  15. 佰马科技参加第16届中国道路照明论坛,助力智慧灯杆建设
  16. html如何插入动图,动态图片如何插入到PPT里?
  17. Nature | 基于深度神经网络和改进的片段测序方法从头预测蛋白质结构
  18. app公司制作app的方法和步骤
  19. 前端过程性考核,肝了一宿终于肝出来了!!!
  20. 华为服务器bmc怎么传文件,华为服务器bmc配置

热门文章

  1. PHP 删除数组中元素的方式
  2. idea 正则表达式搜索替换
  3. Java 组合模式及其应用
  4. java 校验姓名只能包含中英文_java代码验证用户名,支持中英文(包括全角字符)、数字、下划线和减号 (全角及汉字算两位),长度为4-20位,中文按二位计数...
  5. 深度剖析 浮点型 在内存中的存储【C语言】
  6. lookup函数和vlookup_5个实用案例告诉你,为什么说Lookup函数比vlookup更简单
  7. POJ2932Coneology(计算几何、平面扫描)
  8. 【大作业】城市地铁线路最短路规划及路径输出(满分)
  9. 关于神经网络模型的一些入门知识
  10. 33.搜索旋转排序数组