前言

相信大家用了这么久的Mysql,一定很好奇自己写的SQL是如何执行并返回结果的,今天我们就来一层一层剥开Mysql这颗洋葱。

首先我们通过一张图来了解下整个过程,然后再开始一步一步解析。

第一步:客户端发送SQL语句到Mysql服务端

假如项目中用到了Mybatis来操作数据库,那么Mybatis就会通过JDBC来连接数据库,并发送语句给数据库,因为一般运行Web后台服务的机器和Mysql服务都是物理上隔开的,是一个分布式架构,所以需要通过网络来访问,JDBC采用TCP连接的方式与Mysql服务端进行通信,通信的内容包括发送语句、接收执行结果等。虽然TCP是全双工的,但是Mysql的TCP是半双工的,这意味着同一时刻要么客户端在发送数据,要么服务端在发送数据。

第二步:验证连接合法性

JDBC与数据库建立的连接的时候,会要求输入用户名和密码,Mysql需要验证用户名是否存在,密码是否正确。验证通过后,再根据mysql.user表中的host字段来验证客户端IP是否是允许的IP,这个host字段相当于一个白名单。

前面的合法性都通过后,JDBC才会发送实际的SQL语句给Mysql服务端。

第三步:查询缓存

像上面这种SELECT语句,Mysql服务端收到这个SQL时,如果开启了查询缓存,就会根据SQL语句在查询缓存中查找,查找成功就直接返回查询缓存中的结果给客户端,而不会执行下面这些操作。

请注意,这里的查找方式是根据SQL语句进行hash运算,只要SQL中有一个字节不同都不会命中缓存。

第四步:语法解析和预处理

当查询缓存没有命中时,才会开始进行语法解析和预处理。语法解析就像一个编译程序一样,根据语句生成语法树,并检查语法树中的关键字是否正确,顺序是否正确,引号是否前后匹配等。

经过语法解析后,预处理就会检查sql中的表、列是否存在,列名是否有歧义等,同时预处理还会对SQL进行权限认证,比如该用户是否有SELECT权限、INSERT权限..., 是否有对应数据库的权限、表的权限等等。

第五步:查询优化

查询优化主要分为两部分,一是静态优化二是动态优化。静态优化可以把语句中一些where条件进行等价交换,比如:WHERE 1=1 AND a > 2将被替换为WHERE a > 2;静态优化不依赖sql语句的具体值,就像Java静态编译器的语法糖一样。

动态优化:因为动态优化以页为最小单元来评估成本,所以需要分析SQL语句所对应的表的索引页或者数据页的数量,以此来确定是走索引还是全表扫描。这些信息都是通过存储引擎来获得的,所以如果存储引擎给出的结果不精确,那么查询优化的执行计划可能就不是最优的。

因为一条sql可以选择的执行方式有很多种,比如一张表里有多个索引,SQL语句涉及多个表的连接查询,那么得到上述信息后,就需要评估使用哪些索引、哪个表关联的顺序是最优的,并以此来生成一条执行计划。这部分也是Mysql服务层最复杂的地方,因为需要考量的因素有很多,这里笔者只是列出了一小部分。

第六步:调用存储引擎执行

其实在Mysql中,真正决定怎么存储数据和查询数据的组件是存储引擎。所以在第五步中得到了执行计划后,Mysql会调用表所对应的存储引擎的API,来执行真正的查询。Mysql定义了一系列存储引擎接口,来让编写存储引擎的人来实现,所以只要符合接口定义的存储引擎都是可以放入Mysql中去使用的。其中使用最广泛的引擎莫过于InnoDB,InnoDB是一个支持事务、支持崩溃快速恢复的高性能存储引擎。

Mysql服务层和存储引擎层最大的区别是:服务层实现了一些不依赖于具体存储引擎的通用操作,比如上面的连接验证、SQL验证这些。而存储引擎则完成具体的查询存储操作,所以好的存储引擎是Mysql的关键。

第七步:将结果返回给客户端

容易想到的一种方式是Mysql服务端先把查询结果缓存到内存中,然后再一次性发送给客户端,可实际上不是这样的。实际是拿到符合条件的第一条数据就返回给客户端,这是一个增量过程。这样做的原因,是可以缓解服务端的内存压力。

如果开启了查询缓存,并且语句是UPDATE、DELETE、INSERT之类的操作,那么这个时候也会更新查询缓存。

总结

在整个过程中,最复杂的部分是第五步的查询优化和第六步中具体的存储引擎,实现细节是造就了Mysql长盛不衰的原因。如果想要优化Mysql的性能,有几步可以优化:

  1. 客户端使用连接池,这样可以让连接复用,因为Mysql每接收一个连接都要用一个线程去处理,和其他Web服务器的连接池解决的问题一样,这里也可以解决。
  2. 查询缓存虽然在查询时可以避免很多后续操作的成本,但是维护它的成本也挺高的,因为每次UPDATE、DELETE、INSERT都需要互斥地更新对应表的查询缓存,这会成为Mysql的可扩展性瓶颈。根据阿姆达尔定律,决定一个系统能否水平扩展的是程序串行的部分。在Mysql8.0以上版本中,默认禁用了查询缓存。所以除非你能确定查询缓存确实对吞吐量有帮助,否则禁用查询缓存是个好建议。
  3. 默认情况下,客户端在第七步的接收过程中,其实是在自己的内存里缓存了全部结果之后,才会解除阻塞,这些会创建很多对象,当并发增高时,可能会引起JVM的OOM。所以这里可以改为每次只接收部分数据,处理完后再接收部分。但这里服务端对于资源都是持有状态,所以是一个空间和时间上的权衡
  4. 如果有必要,你可以干涉第五步的查询优化过程,Mysql提供一些hint语句,比如强制走规定的关联表顺序或者强制使用某些索引。但是大多数情况下,请不要以为自己比查询优化器更聪明,使用推荐的方案可能更好。
  5. 设计一个好的索引对于查询的性能影响非常之大,所以对于使用关系型数据库来说,索引设计是非常重要的一环。

SQL语句在Mysql中是如何被执行的?相关推荐

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

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

  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. mysql navicat 多语句_使用Navicat多对多关系SQL语句在MySQL中实现

    /** *功能:模拟两张表关系及添加两个主键和外键详细过程 *日期: 2018年7月26日   18:45 *注释: 学习数据库MySQL的点点记录, 谢谢网上各位大神分享经验与资料, 欢迎各位大神批 ...

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

    日常读书笔记

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

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

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

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

  8. mybatisplus执行sql语句_[MySQL]sql语句的执行流程

    此篇极客时间专栏<MySQL实战45讲>笔记,文中部分图文来自该专栏. MySQL的执行流程示意图: 大体来说,MySQL可以分为Server层和存储引擎层两部分. Server层包括连接 ...

  9. sql语句查看MySQL数据库大小

    SQL语句查看MySQL数据库大小 > SELECT table_schema "Database Name", sum( data_length + index_lengt ...

最新文章

  1. eclipse 出现user operation is waiting
  2. Java线程池详解及常用方法
  3. web3.js(一)根据地址查询以太数量
  4. sql server 2008语言基础: 集合
  5. linux wc -l 对io,linux设备驱动归纳总结(五):2.操作硬件——IO内存
  6. smartforms金额或者数量字段显示不出来
  7. CreateThread()与beginthread()的区别详细解析
  8. CentOS添加一个新的硬盘、添加分区到挂载的过程
  9. Spring 事务API 架构图
  10. 数据分析避坑必读:让人怀疑人生的七大悖论
  11. HDU 6185 2017广西邀请赛:Covering(矩阵快速幂)
  12. MooseFS源代码分析(三)
  13. 【中医学】8 中药-3
  14. 《带人要同频,管人要共情》读书笔记
  15. ios android与wp,在iOS与Android间选择WP
  16. 小程序转uniapp——disabled
  17. 源程序、目标程序、汇编程序、编译程序、解释程序
  18. 远程辅助必备免费神器ToDesk远程控制软件(答辩,远程,调试,办公)必备远程工具
  19. linux系统32和64的区别,32位和64位的Linux系统区别
  20. redis修改端口号

热门文章

  1. vue 使用vue-canvas-poster生成自定义海报
  2. Android UI 之WaterFall瀑布流效果
  3. Mac pro 连上wifi 5G提示无ip地址
  4. js pug 代码_Vue项目中配置pug解析支持
  5. 18000担粮草和新四军情报
  6. 第一个报表(简单滴)
  7. 解决Failed to connect to github.com port 443 after 21113 ms: Timed out
  8. 以太坊中metamask、imtoken等钱包签名的php验证
  9. C语言中转义字符的介绍与使用
  10. 淘宝人生3周年,聊聊我们3D互动游戏的项目经验