一条sql语句执行的流程

执行一条select 语句中间会发生什么? 这个是对 mysql 架构的深入理解。在腾讯面试中回到过这样的,一条 sql 语句的执行流程。

select * from product where id = 1;

对于mysql的架构分层图:

alt

mysql 架构分成了 Server 层和存储引擎层:

Sever 层 负责建立连接、分析和执行 sql 语句。 一些核心功能模块比如解析器生成语法树,预处理器、优化器、执行器这些。

在存储引擎层:支持 InnoDB 存储引擎。底层使用的是 B+树。mysql5.5 之后 InnoDb 成为默认的存储引擎了。

第一步建立连接

通过连接器和 mysql 的客户端建立连接,连接的过程需要使用 TCP 三次握手。

msyql -u root -p

在输入对应的密码就登录成功了

查看 mysql 当前有多少连接数量:mysql 默认是 151 条连接。可以设置

show processlist;

执行了一次查询就算建立连接了,连接默认是八个小时,超过这个数量就会自动的断开。

alt

连接数太多了

alt

删除了查询缓存,在 mysql8 之前查询的内容会缓存起来。如果有插入操作,那么缓存就要删除,这样效率并不会很高。

第二部解析 SQL

解析器会做两件事情,第一个是词法分析:

mysql 会根据你输入的字符串识别出关键字出来,比如 select username from userinfo 会解析出来 4 个 token,有两个 key word,是 select 和 from。

第二个进行语法的分析:

根据词法分析的结果,语法解析器根据语法规则判断输入的 sql 是否满足 MYSQL 的语法。没有问题就构建出来 sql 语法树。

构成一个这样的语法树。

alt

https://blog.csdn.net/zhang24360/article/details/128963299 语法树的详细内容

对于这样的一颗语法树使用后序遍历,左右中,这样就能组合成一条 sql 语句出来了。

第三步执行 sql

分为三个阶段 预处理 优化阶段 执行阶段

预处理阶段:

检查 sql 查询语句中的表或者字段是否存在。

将 select * 中的*符号扩展为表上的所有列。

优化阶段:

需要确定一个执行计划,比如现在有多个索引到底用哪一个索引。确定 sql 查询语句的执行方案。

想要知道选择哪个索引可以在查询语句之前加一个 explain 命令,会展示书 sql 语句的查询计划。

alt

优化器是用来选择索引的。查询主键索引的成本会更大,因为主键索引存储的所有数据的值。

在上面的 sql 语句中查询主键索引 B+树的成本会高于查询二级索引 B+树的成本,优化器会基于查询成本考虑选择代价最小的普通索引。

执行阶段:

这个时候 server 层要去和存储引擎层进行交互了:

比如有 全表扫描(b+树支持范围查找)、主键索引查询、索引下推。

索引下推

alt

对于联合索引 遇到> 或者小于< 就会停止匹配。

在 mysql5.6 之前,定位到 age>20 的第一条记录,然后找到主键值,进行回表查询,将完整记录 Server 层,在判断是否相等。 这样每一次查询二级索引记录都要进行回表。

alt

第一次定位到 age>20 的时候,先判断后面的 reward 是否等于 1000.如果成立才进行回表操作。

alt

索引下推是减少二级索引的回表查询操作,提高查询的效率。将 Server 层做的一些事情交给了存储引擎层去做。

查询 age>20 的时候遇到>联合索引就会失效了,这个时候就需要回表查询 reward 是否是等于 1000 的。

这样效率太慢了,直接在存储引擎层去判断 reward 是否等于 1000. 如果成立在回表给 Server 层操作。 alt

最后 sql 执行完成之后返回字节流数据

#sql##mysql执行流程#
牛牛的面试专栏 文章被收录于专栏

牛牛的面试专栏,希望自己在25年可以拿到一份大厂的SP Offer 你的点赞和收藏都是我持续更新的动力

全部评论
😝
点赞 回复 分享
发布于 04-17 17:13 湖南
写的真好
点赞 回复 分享
发布于 04-05 16:07 安徽

相关推荐

05-10 17:11
门头沟学院 Java
秋招过去了好久,是时候更新一下面经了一面-&nbsp;拷打实习项目-&nbsp;实习项目亮点-&nbsp;拷打项目(折磨)-&nbsp;为什么要用两级缓存-&nbsp;caffine淘汰策略(没看过)-&nbsp;为什么本地用top50,我说是top30行不行,(预估,预热)-&nbsp;如果千万级是什么方案-&nbsp;为什么要牺牲一致性(CAP,&nbsp;BASE扯了下)-&nbsp;1000w用户需要怎么做-&nbsp;定时器放在那里-&nbsp;怎么做数据预热-&nbsp;这里battle了巨久,感觉没有回答想要的点-&nbsp;springboot启动流程-&nbsp;java&nbsp;bean是什么(这里我说get&nbsp;set方法,他说应该从IOC里面说)-&nbsp;IOC是什么-&nbsp;IOC有什么好处(说了解耦,他问还有呢,从使用者和组件开发者的角度,我是真不会啊)-&nbsp;又扯了巨久,真不会回答-&nbsp;手撕:验证搜索二叉树二面-&nbsp;项目拷打吧20min,其实感觉也没讲明白-&nbsp;raft协议-&nbsp;raft能应对脑裂吗-&nbsp;ES原理-&nbsp;有实际运维部署经验吗)无-&nbsp;时间久远其他问题记不得了-&nbsp;手撕:交叉链表三面-&nbsp;拷打项目-&nbsp;说说SQL的执行的整个流程-&nbsp;为什么要用逻辑执行计划-&nbsp;你知道MySQL优化器会优化那些内容吗-&nbsp;innodb引擎索引结构-&nbsp;二级索引结构-&nbsp;b+树和b树有什么优势-&nbsp;为什么二级索引叶子节点要放主键值而不是一个指针)说的页分裂不知道对不对-&nbsp;知道最左匹配原则吗-&nbsp;undo&nbsp;log,&nbsp;redo&nbsp;log,&nbsp;bin&nbsp;log都说说-&nbsp;redo&nbsp;log写到内存里如何保证能刷盘(3个参数)-&nbsp;事务两阶段提交的过程-&nbsp;MVCC实现的原理-&nbsp;进程和线程的区别-&nbsp;用户态和内核态的区别-&nbsp;怎么从用户态切换到内核态-&nbsp;在编程的时候如何减少用户态到内核态的切换)这里纯在乱答-&nbsp;协程有了解吗-&nbsp;说下多路IO复用-&nbsp;讲下4次挥手)捏马的有点忘了状态名字了,说了两遍才说懂-&nbsp;为什么time_wait是2MSL为什么不是1MSL,为什么不是3MSL-&nbsp;fork知道吗,fork返回的值是什么-&nbsp;a&nbsp;=&nbsp;fork()&nbsp;b=fork()&nbsp;print(a,b)&nbsp;这个最后产生几个进程,打印的内容是什么-&nbsp;了解哪些排序-&nbsp;快排复杂度推导一下-&nbsp;归并的复杂度推导一下-&nbsp;链表做归并的时候需要从中间节点断开,这个相比归并数组会影响时间复杂度吗-&nbsp;LRU思路讲下-&nbsp;手撕:链表排序-&nbsp;一共一个半小时,强度有点大,有些推导性质的东西确实不记得了,只记得结论了。还得下来多看下
点赞 评论 收藏
分享
评论
点赞
12
分享

创作者周榜

更多
牛客网
牛客企业服务