Stream SQL 的执行原理与 Flink 的实现

  1. 如果一条 SQL 可以使用流式处理来执行,具体要如何实现?我们格外感兴趣的是 Group By 和 Join 操作的实现。

  2. 在了解过 Stream SQL 的基本原理之后,我们进一步感兴趣的问题是现存的系统(特别是 Flink)的相关实现细节。

接下来的文章我们就来讨论这些问题。在增量 SQL 查询算法这一章首先来介绍诸如 Flink 这类系统所采用的实现 Stream SQL 查询的理论, 在流式处理与时间控制这一章,我们将讨论 Stream 处理系统的一些基本的概念和如何操作时间。最后, 我们将会讨论 Apache Flink 的能力与局限,致力于对 Flink 执行相关任务方法的进行一个简单刻画。特别地,我们会花费一些篇幅在 Flink 内部状态的管理。

增量 SQL 查询算法


一般来讲,给定一条 SQL 如果其源数据表中有一些数据发生了改变,我们需要重新全量执行这条 SQL 才能得到更新过的结果。 增量 SQL 查询则意味着我们可以只依赖源数据的改变量,局部地执行查询并更新原来的结果。使用增量模型, 我们往往可以得到更快的执行方案。很显然,Stream SQL 执行就是增量 SQL 查询:新到达的数据就是在一张“源数据表” 当中新加入的数据项。

为了介绍增量 SQL 查询算法,首先来看一些术语的解释:

  1. 视图(View):是在关系型数据库当中被保存的一个查询

  2. 物化视图(Materialized View):是将一个视图的内容“物化/预计算保存”下来的结果

  3. 表(Table):是一类可以支持扫描(Scan)或查询(Query)的数据源

  4. 索引(Index):是附加于表或者视图上用于加快查询的数据结构

请注意,在本文的讨论当中,索引指代的是一类需要引用原始数据的数据结构,也就是说索引只包含了原始数据当中的一部分信息。 包含原数据的全部信息并且可以无损翻译回去的可以认为是物化视图。另外,物化视图显然也是一种表:他支持扫描和查询操作。

容易得到,增量 SQL 查询的问题就是物化视图内容维护的问题。我们显然希望增量地维护物化视图的内容, 而不是每当源数据表改变就全量刷新。

物化视图的概念最早由 Oracle 和 SQL Server 等商业数据库作为索引的一种补充而引入。 学术界和工业界至今已经积累了很多相关研究,从而形成了一整套方法论。 很多现代的流式处理系统也采用了这些方案:Stream SQL 是物化视图维护问题的一个子问题。

为了阐释为什么物化视图是一种有效地加速查询的功能,我们先来花一些时间在 SQL 查询的优化与执行规划问题上。

SQL 优化与执行规划

在 SQL 查询优化原理与 Volcano Optimizer 介绍 一文中,我们已经对相关算法进行了详细介绍。简单重复一下的话,作为一种声明式的查询语言,我们可以将 SQL 转化成一种叫关系代数(Relation Algebra)的抽象表示来进行计算。这样的一种抽象表示被称为 SQL 执行的逻辑计划(Logical Plan)。 逻辑计划一般由一棵算子(Operator)组成的的树表示,这棵树表示了算子之间的依赖关系和执行顺序。特别地, 我们还可以为这课树表示的方案及其每棵子树进行执行花费的估算。下图展示的就是一条 SQL 的执行方案。

640?wx_fmt=jpeg

逻辑计划与成本估算

上图左边是逻辑计划,右侧是对计划成本的估算,其中展示的算子有 Join、Project 和 Filter 等。这里 Project 表示的是对上游输入的每个元素进行变换处理(如选取列、对每行进行数值变换等)的算子。利用右侧成本估算进行 SQL 查询优化的优化器被称为基于成本(Cost-based)的优化器。在实现上, 每个抽象算子可以结合子树传入的成本和自己的内部实现向上返回一个对自己成本的估算。也就是说成本估算是递归执行的。

比较先进的优化器大多基于成本估算,其基本原理是反复应用查询变换的规则将原查询修改为语义相同等另一方案, 在这一过程中不断估算成本并最终选取成本最低的方案。关于高效实现这一思路的 Volcano/Cascades 算法, 前面提到的文章已经进行了充分介绍,这里不再赘述。

在本文的语境当中,值得关注的是这种优化器提供的两种特别的可能性:

  1. 将逻辑计划转换为物理计划的能力

  2. 将整棵子树转换为单个算子节点返回预计算结果的能力

所谓的物理计划,指的是方案中每个算子都包含了执行这个方案所需要的信息的方案。在有的实现中, 物理计划当中的算子可以直接被调用执行。将计划划分为逻辑计划和物理计划的意义在于, 我们可以为语义相同的算子提供不同的物理实现。比方说如下图所示,针对 Join 节点我们有两种不同的实现方法: 使用哈希表的 Hash Join 和使用排序方法的 Sort Join。这两种实现方法有不同的适用场景, 比方说,Hash Join 一般性能较好,但是适用的数据规模有限,而使用外部排序的方法 Sort Join 一般可以支持非常大的数据范围。在现代数据库的优化器当中,这两种物理算子的选取是依据方案的成本估计来选取的。

640?wx_fmt=jpeg

成本估计与物理方案选取

可以看到,在上述方案选取当中,尽管 Hash Join 本身可以以更高的性能执行,然而 Sort Join 可以具备返回有序结果的特性。 因此,在规划时更上层的算子可以利用这一特性

  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值