文章目录
一、概述
1、FLink SQL 优势
在介绍Time Window Join前,可以先看看Flink SQL相关的整体介绍和架构:
- 声明式:用户只需要表达我想要什么,至于怎么计算那是系统的事情,用户不用关心。
自动调优。查询优化器可以为用户的 SQL 生成最有的执行计划。用户不需要了解它,就能自动享受优化器带来的性能提升。- 易于理解:很多不同行业不同领域的人都懂 SQL,SQL 的学习门槛很低,用 SQL 作为跨团队的开发语言可以很大地提高效率。
- 稳定:SQL 是一个拥有几十年历史的语言,是一个非常稳定的语言,很少有变动。所以当我们升级引擎的版本时,甚至替换成另一个引擎,都可以做到兼容地、平滑地升级。
流与批的统一:Flink底层 runtime 本身就是一个流与批统一的引擎。而 SQL 可以做到 API 层的流与批统一。
2、FLink SQL 核心功能
从上图可以看到Aggregation和Join属于SQL中重要的一员,我们在业务场景中,也会经常用到聚合和Join
3、FLink Join的分类
FLink内部实现的Join有多种类型,分为:
1、Join算子(即普通的join,不区分condition里面的时间条件,左右两侧流数据可以长时间保存)
2、Join LETERAL(右表是一个自定义函数TableFunction实现的视图,遍历进行Join)
3、Join Temporal Table时态表(右表是通过registerTemporalTable注册,join的时候,右表返回指定时间范围内,最新的数据,例如计算汇率的场景)
4、维表Join(分同步和异步两种方式,可以查询数据库数据,补全流中字段信息,例如补全订单用户名场景)
5、Time Window Join(也可以叫做Time Interval Join,即Join条件中,带有时间范围的双流Join,例如订单表和付款表进行补全的场景,付款有1小时时效信息)
4、Join图示
双流Join(条件中未带时间信息):
维表Join(SQL语句中具有FOR SYSTEM_TIME关键字):
Time Window Join(条件上带有BETWEEN … AND时间表达式):
SELECT
o.orderId,
o.productName,
p.payType,
o.orderTime,
cast(payTime as timestamp) as payTime
FROM
Orders AS o JOIN Payment AS p ON
o.orderId = p.orderId AND
p.payTime BETWEEN orderTime AND
orderTime + INTERVAL ‘1’ HOUR
本文重点讨论Time Window Join,其余4种Join类型,后续我们有时间再逐一讨论。
二、创建Time Window Join Function
1、测试用例
在进行源码分析前,我们先引入FLink 1.9.0源码中提供的测试用例,本文后续章节也根据这个用例展开,并附带一些Debug调试数据,来加深对源码的理解:
源码中,WindowJoinITCase#testRowTimeLeftOuterJoin()测用例如下:
class WindowJoinITCase(mode: StateBackendMode) extends StreamingWithStateTestBase(mode) {
@Test
def testRowTimeLeftOuterJoin(): Unit = {
val sqlQuery =
"""
|SELECT t1.key, t2.id, t1.id
|FROM T1 AS t1 LEFT OUTER JOIN T2 AS t2 ON
| t1.key = t2.key AND
| t1.rowtime BETWEEN t2.rowtime - INTERVAL '5' SECO