Flink Joins(SQL篇)

(TODO)

双流 Join(Regular Join)

1
2
3
SELECT *
FROM Orders
INNER JOIN Product ON Orders.productId = Product.id

要点:

  • 支持INNER JOINLEFT JOINRIGHT JOINFULL OUTER JOIN
  • 仅支持等值连接条件;
  • 为了计算查询结果,需要将左右两端的流都持久性保持在状态中,因此中间状态可能会无限增长,这具体取决于两端输入表中的distinct行数和中间连接结果中的distinct行数;
  • 配置状态TTL防止状态无限增长;

区间 Join(Interval Join)

1
2
3
4
SELECT *
FROM Orders o, Shipments s
WHERE o.id = s.order_id AND
s.ship_time BETWEEN o.order_time AND o.order_time + INTERVAL '4' HOUR

要点:

  • 区间连接需要至少有一个“等值连接条件”,以及一个限定两端时间的连接条件;
  • 支持INNER JOINLEFT JOINRIGHT JOINFULL OUTER JOIN
  • 输入表必须是有时间属性的append-only表,支持Processing Time和Event Time;
  • 左右流都会触发结果更新;
  • State 自动清理,根据时间区间保留数据;
  • 输出流保留时间属性;

区间Join中的连接条件

Interval Join中需要有连接条件对两端的流进行限制。可以使用:

  • 区间的形式:使用< <= >= >或使用BETWEEN ... AND ...
  • 或在两端表的相同类型的时间属性(例如,处理时间或事件时间)使用等值连接条件;

以下示例都是合法的区间连接条件:

  • ltime = rtime
  • ltime >= rtime AND ltime < rtime + INTERVAL '10' MINUTE
  • ltime BETWEEN rtime - INTERVAL '10' SECOND AND rtime + INTERVAL '5' SECOND

下面我们来分析一下Interval Join中的连接条件是如何限制两端状态的。如图,我们的业务场景是:对订单流和配送流进行连接,约束为:收到订单4小时以内进行配送的订单。

  • 左图,当订单流中的watermark到达10:15,为了满足约束条件,配送状态只需要保持配送时间在10:15~14:15范围之内的数据,10:15是配送状态的下限,所以配送时间在10:15之前的配送状态都可以不再维护,这样就定义了配送流的下限;
  • 右图,当配送流中的watermark到达12:00,为了满足约束条件,订单状态只需要保持下单时间在8:00~12:00范围之内的数据,8:00是订单状态的下限,所以下单时间在8:00之前的配送状态都可以不再维护,这样就定义了订单流的下限;

时态表Join(Temporal Join)

参考

  1. 基于 Flink 的典型 ETL 场景实现
  2. 基于 FLINK SQL 的实时数据打宽PPT链接演示代码链接
  3. https://nightlies.apache.org/flink/flink-docs-release-1.13/zh/docs/dev/datastream/operators/joining/
  4. https://nightlies.apache.org/flink/flink-docs-release-1.13/zh/docs/dev/table/sql/queries/joins/
  5. https://www.slideshare.net/FlinkForward/flink-forward-san-francisco-2019-how-to-join-two-data-streams-piotr-nowojski