经过一周的持续整理与总结,终于完成了一条简单查询语句执行过程各个阶段分析的文章。写文章的过程,既是分享输出的过程,也是重新学习的过程。
在这个过程中,也有不小的收获,自己知道和写出来让大家都知道,这个知识转换输出的过程,并不是件容易的事,需要对知识点有更深刻的理解。研究源码时以为自己已经理解的一些知识点,在写文章的过程中,发现并不能清楚的写出来,这时候又继续回头去研究源码,对于这类知识点又有了更深刻的理解。
也感谢同事、朋友们帮忙转发,传播文章,第一次体验到自己写的东西有人在看,这种感觉也是不错的,虽然现在看的人还少,我也会持续输出,一方面是提升自己,另一方面也希望给有需要的小伙伴带来一些帮助。
由于查询语句执行过程涉及的环节比较多,整个执行过程拆分为6篇进行介绍,为了小伙伴们对执行过程有个整体的了解,有必要对每篇文章中的内容做一个概括性总结。
1.词法分析语法分析-点击阅读
第1篇,先介绍了MySQL词法分析器是自己实现的,并没有使用开源工具,猜测主要是因为开源的词法分析器要兼顾通用性,不如自己实现执行效率高。
然后介绍了MySQL语法分析器使用了开源工具Bison,因为语法分析器相比于词法分析器来说,没有那么多复杂的逻辑,主要都是针对语法的处理,所以用开源工具实现不涉及到执行效率问题,践行了不重复发明轮子的理念。
最后介绍了在词法分析语法分析过程中,会初始化select子句中的字段为Item_field类实例,初始化from子句中的表为TABLE_LIST类实例,初始化where条件中的字段为Item_field类实例。
2.查询准备阶段-点击阅读
第2篇,先介绍了打开表的过程,涉及到表缓存(TABLE类实例缓存)、表定义缓存(TABLE_SHARE类实例缓存)、读取frm文件。
然后介绍了把select子句中的星号(*)替换为表字段的过程。
最后介绍了where条件中的Item_field类实例找到其对应字段Field类实例的过程,并设置字段内容和where条件中的值进行比较时执行的函数。找到Item_field类对应字段Field类实例的过程中,使用了两级缓存,以及兜底逻辑:循环遍历表中字段。
3.从InnoDB读数据-点击阅读
第3篇,以InnoDB为例讲述从存储引擎中读取数据的过程,先介绍了创建InnoDB存储引擎实例,在这个过程中会建立MySQL和InnoDB索引的映射关系,以及会创建用于InnoDB执行查询过程的查询模板。
然后是填充查询模板的过程,主要介绍了文中示例SQL执行时涉及到的三个方面,分别是:根据查询优化阶段确定的要使用的索引,找到InnoDB中索引的实例;对回表的概念进行了说明;以及InnoDB会返回哪些字段的内容给server层,又是怎么返回内容的?
最后是InnoDB执行查询的过程,先介绍了什么是预读缓存,以及什么情况下会使用预读缓存;简单介绍了InnoDB都是从BufferPool中读取数据;InnoDB怎么通过一致性视图判断记录是否可见。
4.WHERE条件-点击阅读
第4篇,先介绍了where条件在源码中实现为类似树状的结构,并用一张图呈现了示例SQL中where条件的结构。
然后介绍了从存储引擎读取到的记录和where条件中的值进行比较的过程。
最后介绍了三种特殊类型的字段(set、enum、bit)作为where条件时,是怎么和记录中的字段内容进行比较的。
5.发送数据给客户端-点击阅读
第5篇,先介绍了MySQL会发送字段的哪些元数据信息给客户端,然后介绍各种类型字段,在发送给客户端之前,是怎么转换为字符串格式的,以及还会做哪些逻辑处理。
6.网络缓冲区-点击阅读
第6篇,从客户端和服务端数据交互的基本单元数据包(Packet)开始,介绍了MySQL中的连接缓冲区、结果集缓冲区,它们的自动增长逻辑和上下限;超过16M的大数据怎么发送和接收;两个系统变量net_buffer_length、max_allowed_packet的配置,以及一个不起眼的小东西BlockSize。
这次的查询语句执行过程分析,以一条简单查询语句为基础,也是我写执行过程分析系列文章的基础篇,接下来计划要写的方向有这些:
文件排序groupby使用索引的执行过程groupby使用临时表的执行过程内存临时表磁盘临时表聚合函数的实现查询优化器子查询优化表上拉(TablePullout)重复值消除(DuplicateWeedout)首次匹配(FirstMatch)松散扫描(LooseScan)子查询物化连接连接(Join)查询欢迎