1. FlinkSql 快速认识

1. FlinkSql 快速认识

1.1 基本原理和架构

Flink Sql是架构于Flink core之上用sql语义方便快捷的进行结构化数据处理的上层库;
(非常类似Spark sql和Spark core的关系)

整体架构和工作流程

核心工作原理如下:

  • 将数据源(数据集),绑定元数据(schema)后,注册成catalog中的表(table,view);
  • 然后由用户通过tableAPI或者sql来表达计算逻辑
  • 由table-planner利用apache calcite对sql语义解析,绑定元数据得到逻辑执行计划
  • 再用Optimizer进行优化后,得到物理执行计划
  • 物理计划经过代码生成器后生成代码,得到Transformation Tree
  • Transformation Tree转成JobGraph后提交到Flink集群执行
FlinkSql图1
关于元数据管理
FlinkSql图2 FlinkSql图3
关于逻辑执行计划
FlinkSql图4
关于查询优化
FlinkSql图5

Flink Sql中有两个优化器

  • RBO(基于规则的优化器)
  • CBO(基于代价的优化器)
RBO(基于规则的优化器)

遍历一系列规则(RelOptRule),只要满足条件就对原来的计划节点(表达式)进行转换或调整位置,生成最终的执行计划。 
常见的规则包括:

  • 分区裁剪(Partition Prune)、列裁剪
  • 谓词下推(Predicate Pushdown)、投影下推(Projection Pushdown)、聚合下推、limit下推、sort下推
  • 常量折叠(Constant Folding)
  • 子查询内联转join等
RBO优化示意图

常量折叠

FlinkSql图6

谓词下推

FlinkSql图7

投影下推

FlinkSql图8

CBO(基于代价的优化器)

会保留原有表达式,基于统计信息和代价模型,尝试探索生成等价关系表达式,最终取代价最小的执行计划。
CBO的实现有两种模型

  • Volcano模型
  • Cascades模型

这两种模型思想很是相似,不同点在于Cascades模型一边遍历SQL逻辑树,一边优化,从而进一步裁剪掉一些执行计划。

CBO优化示意图

根据代价cost选择批处理join有方式(sortmergejoin、hashjoin、boradcasthashjoin)。
比如前文中的例子,在filter下推之后,在t2.id<1000的情况下,由1百万数据量变为了1千条,计算cost之后,使用broadcasthashjoin最合适。

FlinkSql图9

物理计划 --> Transformation Tree

FlinkSql图10

1.2 动态表特性

与spark、hive等组件中的“表”的最大不同之处:Flink Sql中的表是动态表!
这是因为:

  • Flink对数据的核心抽象是“无界(或有界)”的数据流
  • 对数据处理过程的核心抽象是“流式持续处理”

因而,Flink Sql对“源表(动态表)”的计算及输出结果(结果表),也是流式、动态、持续的;

  • 数据源的数据是持续输入
  • 查询过程是持续计算
  • 查询结果是持续输出

如下图所示:

  • “源表clicks”是流式动态的
  • “聚合查询的输出结果表”也是流式动态的

FlinkSql图11

这其中的动态,不仅体现在“数据追加”,对应输出结果表来说,“动态”还包含对“前序输出结果”的“撤回(删除)”、“更新”等模式;

而Flink Sql如何将这种对于“前序输出的修正”表达给下游呢?
它的核心设计是在底层的数据流中为每条数据添加“ChangeMode(修正模式)”标记,而添加了这种ChangeMode标记的底层数据流,取名为changelogStream;

FlinkSql图12

FlinkSql图13

在Flink1.12之前,动态表所对应的底层stream,有3种:

  • Append-only stream
  • Retract stream
  • Upsert stream

现在,统称为changelog stream