「分布式技术专题」剖析一个 SQL 的解析及执行过程

原创
02/05 16:00
阅读数 4.5K

无所不能的程序猿吐出一句魔法 SQL ,刹那间,IO 犹如千军万马奔流不息,内存似鲸吸牛饮,海纳百川,CPU 更是狂暴着以 360% 负荷高速运转,瞬间,一个美妙的身影出现了……
一条SQL的背后,数据库到底做了什么,本文将深入浅出的聊一下 SQL 的解析和执行过程。

1. SQL简介

SQL 是上世纪 70 年代,基于关系型数据库发明的一种简洁的数据操作语言。
SQL 按功能可以分为以下三种类型:

业务模型与 SQL 的关系:SQL 是业务本质的浓缩,如以下银行或证券行业的常见业务:

每个业务模型,最终都会转化为一条SQL语句的执行。SQL中包含了你要查询的实体表名称,分组、排序字段,过滤条件等等。

2. SQL的生命周期

生活中,我们做事的步骤一般是先设定目标、然后制定计划、最后实践。
数据库中,一条 SQL 语句就是要完成的目标;SQL 会被编译器解析生成执行计划;最后交由执行器去存储引擎中完成实际的数据操作。
详细的生命周期可以划分为建立连接、词法和语法解析、逻辑计划、RBO 和 CBO 优化、执行计划、权限检查、资源调度、分布式任务执行、返回最终结果等阶段。

2.1 建立连接

客户端使用 JDBC 或 ODBC 协议,提交一个 SQL ,到服务器端。

2.2 词法和语法解析

词法分析是编译过程的第一个阶段,目的是将输入的各种符号,转化成相应的标识符(token),可以被后续阶段处理。
词法分析程序一般称之为Lexical analyzer 或 Scanner。


语法分析是编译过程的一个逻辑阶段; 此阶段的任务是在词法分析的基础上将单词序列组合成各类语法短语、表达式等。 语法分析程序一般称之为 Parser
SQL 解析的本质是语言转换,就是把文本代码转换成计算机语言能描述的数据结构。

  • 常用 SQL 编译工具介绍
    • lexical compiler ,是一个词法分析器(scanner)的生成工具, 使用正则表达式来描述各个词法单元。
    • Yacc 是一个经典的生成语法分析器的工具,采用自下而上(LALR)语法分析方法。 可以将任何一种编程语言的所有语法翻译成针对此种语言的 Yacc 语法解析器。但是其生成的代码一般都比较晦涩难懂。
    • Lex 和Yacc 可以结合使用。
    • ANTLR 是采用 java 编写的,基于自顶向下的递归下降 LL 算法实现的语法解析器生成器。SQL解析的结果是生成抽象语法树 AST(abstract syntax tree)。

2.3 逻辑计划

AST 会被解析成一个逻辑计划,包含用户书写的数据处理逻辑及顺序。
逻辑处理顺序,指的是一条 SQL 语句应该如何执行,每一个关键字、子句部分在什么时刻执行。

需要注意的是,SQL 的执行顺序,并不是按书写顺序从上到下,从左到右执行的。
下面列出了一个标准SQL的实际数据处理顺序:

可以看出,操作的顺序是先选定需要操作的表,之后使用 on 和 where 条件过滤,然后按业务进行分区重组,最后进行排序操作。

2.4 RBO 和 CBO优化

由于用户的能力不同,同一个业务书写出来的SQL脚本可能千差万别,这样会导致逻辑计划可能不是最优的执行路径。所以逻辑计划需要被优化。
数据库一般有两种查询优化器:

  • RBO: Rule-Based Optimization 基于规则的优化器
    • SQL的执行计划。比如查询时索引的优先级大于全表扫描属于 RBO 优化,谓词下推也属于 RBO 优化。
  • ​​​​​​​CBO: Cost-Based Optimization 基于代价的优化器
    • ​​​​​​​CBO 会通过根据统计信息(Statistics)和代价模型(Cost Model)计算各种可能“执行计划”的“代价”, 即 COST,从中选用 COST 最低的执行方案,作为实际运行方案。
    • IO、网络 IO、CPU 的使用情况。 对表做预分析,就是预先统计表的分布和数据量,属于 CBO 优化。

2.5 执行计划

逻辑计划经过 RBO 和 CBO 优化之后,就会生成执行计划。
分布式数据库中,执行计划是可以分布式并行执行的,其任务之间的关系可以看作是一个有向无环图 DAG。

上图中的执行计划被拆分成了 4 个子任务,每个任务都可以被提交到一个或者多个节点上执行。

2.6 权限控制

用户在提交 SQL 时,是附带了个人身份认证信息的,权限控制会校验当前用户是否有 SQL 中对应 DDL/ DCL/ DML/ 等权限。

2.7 资源调度

权限审核通过后,任务将被发送到各个执行节点的任务队列上。每个任务需要先申请相应的 CPU 和内存资源,准备就绪后,才能真正的执行。
在大数据体量下,CPU 和内存资源的消耗是非常巨大的,这也是为什么大数据量的并发查询,有时慢的像蜗牛一样。

2.8 分布式任务执行

前面说过分布式任务之间的关系可以看作是一个有向无环图 DAG,每一个子任务完成后,都会将结果作为下一个任务的输入继续执行,直到完成最顶层的任务。
一般来说,最底层的任务(带有 TableScan 算子)都属于 IO 密集型的,需要从磁盘中读取所需的数据,中间任务(带有 Filter 或 Join 算子)是需要 CPU 进行判断或者做笛卡尔积操作等大量计算,而一些排序操作则需要大量的内存参与。

2.9 返回最终结果

待所有的任务完成并汇总到根节点时,服务器便将 SQL 的执行结果返回给客户端。
以上为剖析一个 SQL 的解析及执行过程,「分布式技术专题」是国产数据库 Hubble 团队精心整理编辑,专题会持续更新,欢迎大家保持关注。

展开阅读全文
打赏
8
9 收藏
分享
加载中
打赏
0 评论
9 收藏
8
分享
返回顶部
顶部