前言
Flink SQL 引擎的工作流总结如图所示。
从图中可以看出,一段查询 SQL / 使用TableAPI 编写的程序(以下简称 TableAPI 代码)从输入到编译为可执行的 JobGraph 主要经历如下几个阶段:
- 将 SQL文本 / TableAPI 代码转化为逻辑执行计划(Logical Plan)
- Logical Plan 通过优化器优化为物理执行计划(Physical Plan)
- 通过代码生成技术生成 Transformations 后进一步编译为可执行的 JobGraph 提交运行
例子1 :考虑如下表达 JOIN 操作的一段 SQL。
SELECT t1.id, 1 + 2 + t1.value AS v
FROM t1, t2
WHERE t1.id = t2.id AND t2.id < 1000
一、Logical Planning(逻辑执行计划)
Flink SQL 引擎使用 Apache Calcite SQL Parser 将 SQL 文本解析为词法树,SQL Validator 获取 Catalog 中元数据的信息进行语法分析和验证,转化为关系代数表达式(RelNode),再由 Optimizer 将关系代数表达式转换为初始状态的逻辑执行计划。
备注:TableAPI 代码使用 TableAPI Validator 对接 Catalog 后生成逻辑执行计划。
二、 Physical Planning on Batch(物理执行计划)
通过上述一系列操作后,得到了优化后的逻辑执行计划。逻辑执行计划描述了执行步骤和每一步需要完成的操作,但没有描述操作的具体实现方式。而物理执行计划会考虑物理实现的特性,生成每一个操作的具体实现方式。比如 Join 是使用 SortMergeJoin、HashJoin 或 BroadcastHashJoin 等。优化器在生成逻辑执行计划时会计算整棵树上每一个节点的 Cost,对于有多种实现方式的节点(比如 Join 节点),优化器会展开所有可能的 Join 方式分别计算。最终整条路径上 Cost 最小的实现方式就被选中成为 Final Physical Plan。
回顾上述的例子1 ,当它以批模式执行,同时可以拿到输入表的 Statistics 信息。在经过前述优化后,表 t2 到达 Join 节点时只有 1,000 条数据,使用 BroadcastJoin 的开销相对最低,则最终的 Physical Plan 如下图所示。
三、Translation & Code Generation(转换算子)
代码生成(Code Generation) 在计算机领域是一种广泛使用的技术。在 Physical Plan 到生成 Transformation Tree (转换算子树)过程中就使用了 Code Generation。
回顾例子1 ,以 表 t2 之上的 Calc 节点 t2.id < 1000 表达式为例,通过 Code Generation 后生成了描述 Transformation Operator(flink转换算子) 的一段 Java 代码,将接收到的 Row 中 id < 1000 的 Row 发送到下一个 Operator。
Flink SQL 引擎会将 Physical Plan 通过 Code Generation 翻译为 Transformations,再进一步编译为可执行的 JobGraph。
内容有误请指出~
参考文章:
https://developer.aliyun.com/article/765311