当前位置: 首页 > news >正文

MySQL学习笔记:一条SQL语句的执行过程

MySQL数据库的组成

如图所示,MySQL由Server层和存储引擎层两部分组成:
图片来源:j极客时间:MySQL实战45讲

Server层

Sever层包括连接器、查询缓存、分析器、优化器、执行器等,主要参与数据库连接、SQL解析执行;所有的内置函数,如日期、时间、数学和加密函数等、所有跨存储引擎的功能,如存储过程、触发器、视图等也都是在该层实现的。

存储引擎层

存储引擎层主要负责数据的存取,常见存储引擎包括InnoDB、MyISaM、Memory等,InnoDB是现在MySQL默认的存储引擎。

一条SQL语句的执行

以 select * from T where k=1 为例

连接器

顾名思义,连接器负责数据库的连接,校验身份、保持客户端与MySQL的连接就是它的责任。
使用如下命令建立连接:

mysql -h$ip -P$port -u$user -p

输入完用户名与密码之后,连接器会校验是否匹配,若登陆成功则查找用户对应的权限,之后通过该连接做的所有查询都是基于此权限,这也意味着一旦连接建立,即使用户权限被更改,也不会影响已建立连接的查询。
连接建立后若8小时没用相关操作连接器就会自动断开该连接,8小时可以通过参数wait_timeout控制。
数据库里面,长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个。
连接过程是使用TCP协议的,所以为了性能应该尽量减少建立连接的动作,即尽量多使用长连接。
长连接实际上是一种空间换时间的做法,因为MySQL临时使用的内存是管理在连接对象里面的,长连接如果持续累计下来可能导致内存占用太大,导致MySQL异常重启。

查询缓存

连接建立完成后,你就可以执行 select 语句了。执行逻辑就会来到第二步:查询缓存。
对于查询过的SQL语句,MySQL会将结果以Key-Value的形式保存下来,如果新来的查询命中了缓存,则会直接返回结果,效率很高。
但是在MySQL8.0查询缓存已经被彻底抛弃掉了,因为通常情况下,查询缓存的失效特别频繁(某个表有更新,该表的所有查询缓存都会清空),命中率极低。

分析器

如果没有某种查询缓存,就需要真正执行SQL语句了,分析器首先会做词法分析,将SQL语句转换为类似“抽象语法树(AST)”的结构,明白字符串中各个字符分别代表什么,做完了词法分析,就会进行语法分析的步骤,可以理解成鉴别词法分析的“词”以语句的方式组合是否会有问题。值得注意的是,语法分析是能够读取到表的信息的(列名,而非具体数据),所以关于字段名是否存在也是在该步骤校验的。

优化器

通过了语法分析,MySQL还会将当前的语句执行步骤做优化,例如:
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。
这两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。
优化器阶段完成后,这个语句的执行方案就确定下来了,然后进入执行器阶段。

执行器

开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误,如下所示 (在工程实现上,如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证。查询也会在优化器之前调用 precheck 验证权限)。
校验权限通过后,执行器会调用存储引擎接口去取T表的第一行,判断 k 是否为1,如果是则将该行保存在结果集中,然后调用引擎接口取“下一行”,重复上述判断逻辑,直到遍历完整个表。
对于有索引的表,执行的逻辑也大同小异,无非是索引能够使得查询更加高效,可以避免一些无意义的遍历。
在数据库的慢查询日志中有一个 rows_examined 字段,该字段代表语句执行过程中扫描了多少行,但在有些场景下,执行器调用一次,内部引擎同时会扫描多行,因此引擎扫描行数跟 rows_examined 并不是完全相同的

参考资料
极客时间《MySQL实战45讲》 01

相关文章:

  • Springboot框架建立(1)
  • mongodb数据模型设计
  • Java学习笔记:SQLite数据库
  • 通过mockjs生成随机响应数据
  • VGG16-好莱坞明星识别
  • 《运营商劫持, 中间人攻击, 黑客入侵怎么办?》- HTTPS 技术反制
  • Vue项目的记录(七)
  • 【云原生 • Kubernetes】集群资源监控概述、监控平台的搭建
  • SpringCloud Stream基本使用
  • 没有CANdela,无法编辑cdd数据库文件,也能轻松完成诊断测试,立省大二十个w
  • 【Linux】基本指令 (下篇)
  • 博途PLC的模糊PID(Matlab “fuzzy“工具箱使用介绍)
  • 【Vue 开发实战】实战篇 # 45:如何构建可交互的组件文档让代码高亮的显示在页面
  • m分别通过matlab和FPGA实现基于高阶循环谱的信号载波调制识别(四阶循环累量)仿真(包括仿真录像,matlab工程,fpga工程)
  • 前端知识体系
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • bearychat的java client
  • Idea+maven+scala构建包并在spark on yarn 运行
  • JDK9: 集成 Jshell 和 Maven 项目.
  • Leetcode 27 Remove Element
  • Magento 1.x 中文订单打印乱码
  • Protobuf3语言指南
  • Redis学习笔记 - pipline(流水线、管道)
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • 基于axios的vue插件,让http请求更简单
  • 前端临床手札——文件上传
  • 入门级的git使用指北
  • 设计模式走一遍---观察者模式
  • 思维导图—你不知道的JavaScript中卷
  • 微服务核心架构梳理
  • Java总结 - String - 这篇请使劲喷我
  • Semaphore
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (175)FPGA门控时钟技术
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (力扣题库)跳跃游戏II(c++)
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (四)模仿学习-完成后台管理页面查询
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转)ABI是什么
  • (转)Unity3DUnity3D在android下调试
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • .gitignore文件—git忽略文件
  • .NET Framework 服务实现监控可观测性最佳实践
  • .NET WebClient 类下载部分文件会错误?可能是解压缩的锅
  • .NET 中 GetProcess 相关方法的性能
  • .netcore如何运行环境安装到Linux服务器
  • .NET值类型变量“活”在哪?
  • [ element-ui:table ] 设置table中某些行数据禁止被选中,通过selectable 定义方法解决
  • []常用AT命令解释()
  • [C#]winform利用seetaface6实现C#人脸检测活体检测口罩检测年龄预测性别判断眼睛状态检测
  • [c]扫雷