Flink sql join

目录

Flink SQL 支持的 Join类型

Regular Join

特性

应用场景

分类

SQL语义

案例

Inner Join

Left Join

Full Join

Interval Join(时间区间 Join)

特性

应用场景

分类

SQL语义

案例

Inner Interval Join

Left Interval Join

Full Interval Join

Temporal Join(时态join)

特性

应用场景

SQL语义

案例

事件时间语义案例

处理时间语义案例

Lookup Join(维表 Join)

特性

应用场景

维表

 SQL语义

案例

Array Expansion(数组列转行)

应用场景

案例

Table Function(自定义列转行)

应用场景

Table Function 使用分类

案例

总结对比


Flink SQL 支持的 Join类型

  1. Regular Join:流与流的 Join,包括 Inner Equal Join、Outer Equal Join
  2. Interval Join:流与流的 Join,两条流一段时间区间内的 Join
  3. Temporal Join:流与流的 Join,包括事件时间,处理时间的 Temporal Join,类似于离线中的快照 Join
  4. Lookup Join:流与外部维表的 Join
  5. Array Expansion:表字段的列转行,类似于 Hive 的 explode 数据炸开的列转行
  6. Table Function:自定义函数的表字段的列转行,支持 Inner Join 和 Left Outer Join

Regular Join

Regular Join 其实就是和离线 Hive SQL 一样的 Regular Join,通过条件关联两条流数据输出,支持 Batch\Streaming

对于流式查询,双流join的语法是最灵活的,允许任何类型的更新(插入、更新、删除)输入表。然而,此操作具有重要的操作含义:它需要将连接输入的两侧永远保持在Flink状态。因此,根据所有输入表和中间联接结果的不同输入行的数量,计算查询结果所需的状态可能会无限增长。可以为查询配置提供适当的状态生存时间(TTL),以防止状态大小过大。同时,这可能会影响查询结果的正确性。

因为资源问题 Regular Join 通常是不可持续的,一般只用做有界数据流的 Join。

特性

  • 支持INNER、LEFT、RIGHT、FULL OUT JOIN
  • 左右流都可以触发更新
  • 实时 Regular Join 可以不是 等值 join等值 join 和 非等值 join 区别在于,等值 join 数据 shuffle 策略是 Hash,会按照 Join on 中的等值条件作为 id 发往对应的下游;非等值 join 数据 shuffle 策略是 Global,所有数据发往一个并发,按照非等值条件进行关联
  • 状态持续增长,一般结合 state TTL配合使(流的上游是无限的数据,所以要做到关联的话,Flink 会将两条流的所有数据都存储在 State 中,所以 Flink 任务的 State 会无限增大,因此需要为 State 配置合适的 TTL,以防止 State 过大)

应用场景

Join 其实在我们的数仓建设过程中应用是非常广泛的。离线数仓可以说基本上是离不开 Join 的。那么实时数仓的建设也必然离不开 Join,比如日志关联扩充维度数据,构建宽表;日志通过 ID 关联计算 CTR

分类

其中以 L 作为左流中的数据标识,R 作为右流中的数据标识

  • Inner Join(Inner Equal Join):流任务中,只有两条流 Join 到才输出,输出 +[L, R]
  • Left Join(Outer Equal Join):流任务中,左流数据到达之后,无论有没有 Join 到右流的数据,都会输出(Join 到输出 +[L, R],没 Join 到输出 +[L, null]),如果右流之后数据到达之后,发现左流之前输出过没有 Join 到的数据,则会发起回撤流,先输出 -[L, null],然后输出 +[L, R]
  • Right Join(Outer Equal Join):有 Left Join 一样,左表和右表的执行逻辑完全相反
  • Full Join(Outer Equal Join):流任务中,左流或者右流的数据到达之后,无论有没有 Join 到另外一条流的数据,都会输出(对右流来说:Join 到输出 +[L, R],没 Join 到输出 +[null, R];对左流来说:Join 到输出 +[L, R],没 Join 到输出 +[L, null])。如果一条流的数据到达之后,发现之前另一条流之前输出过没有 Join 到的数据,则会发起回撤流(左流数据到达为例:回撤 -[null, R],输出 +[L, R],右流数据到达为例:回撤 -[L, null],输出 +[L, R]

SQL语义

SELECT * FROM Orders
[INNER|RIGHT|LEFT|FULL OUTER] JOIN Product
ON Orders.productId = Product.id

案例

曝光日志关联点击日志筛选既有曝光又有点击的数据,并且补充点击的扩展参数(show inner click)

Inner Join
-- 曝光日志数据
CREATE TABLE show_log_table (
    log_id BIGINT,
    show_params STRING
) WITH (
  'connector' = 'datagen',
  'rows-per-second' = '2',
  'fields.show_params.length' = '1',
  'fields.log_id.min' = '1',
  'fields.log_id.max' = '100'
);

-- 点击日志数据
CREATE TABLE click_log_table (
  log_id BIGINT,
  click_params     STRING
)
WITH (
  'connector' = 'datagen',
  'rows-per-second' = '2',
  'fields.click_params.length' = '1',
  'fields.log_id.min' = '1',
  'fields.log_id.max' = '10'
);

CREATE TABLE sink_table (
    s_id BIGINT,
    s_params STRING,
    c_id BIGINT,
    c_params STRING
) WITH (
  'connector' = 'print'
);

-- 流的 INNER JOIN,条件为 log_id
INSERT INTO sink_table
SELECT
    show_log_table.log_id as s_id,
    show_log_table.show_params as s_params,
    click_log_table.log_id as c_id,
    click_log_table.click_params as c_params
FROM show_log_table
INNER JOIN click_log_table ON show_log_table.log_id = click_log_table.log_id;


-- 输出结果
+I[5, d, 5, f]
+I[5, d, 5, 8]
+I[5, d, 5, 2]
+I[3, 4, 3, 0]
+I[3, 4, 3, 3]
...
Left Join
CREATE TABLE show_log_table (
    log_id BIGINT,
    show_params STRING
) WITH (
  'connector' = 'datagen',
  'rows-per-second' = '1',
  'fields.show_params.length' = '3',
  'fields.log_id.min' = '1',
  'fields.log_id.max' = '10'
);

CREATE TABLE click_log_table (
  log_id BIGINT,
  click_params     STRING
)
WITH (
  'connector' = 'datagen',
  'rows-per-second' = '1',
  'fields.click_params.length' = '3',
  'fields.log_id.min' = '1',
  'fields.log_id.max' = '10'
);

CREATE TABLE sink_table (
    s_id BIGINT,
    s_params STRING,
    c_id BIGINT,
    c_params STRING
) WITH (
  'connector' = 'print'
);

INSERT INTO sink_table
SELECT
    show_log_table.log_id as s_id,
    show_log_table.show_params as s_params,
    click_log_table.log_id as c_id,
    click_log_table.click_params as c_params
FROM show_log_table
LEFT JOIN click_log_table ON show_log_table.log_id = click_log_table.log_id;


-- 输出结果
+I[5, f3c, 5, c05]
+I[5, 6e2, 5, 1f6]
+I[5, 86b, 5, 1f6]
+I[5, f3c, 5, 1f6]
-D[3, 4ab, null, null]
-D[3, 6f2, null, null]
+I[3, 4ab, 3, 765]
+I[3, 6f2, 3, 765]
+I[2, 3c4, null, null]
+I[3, 4ab, 3, a8b]
+I[3, 6f2, 3, a8b]
+I[2, c03, null, null]
...
Full Join
CREATE TABLE show_log_table (
    log_id BIGINT,
    show_params STRING
) WITH (
  'connector' = 'datagen',
  'rows-per-second' = '2',
  'fields.show_params.length' = '1',
  'fields.log_id.min' = '1',
  'fields.log_id.max' = '10'
);

CREATE TABLE click_log_table (
  log_id BIGINT,
  click_params     STRING
)
WITH (
  'connector' = 'datagen',
  'rows-per-second' = '2',
  'fields.click_params.length' = '1',
  'fields.log_id.min' = '1',
  'fields.log_id.max' = '10'
);

CREATE TABLE sink_table (
    s_id BIGINT,
    s_params STRING,
    c_id BIGINT,
    c_params STRING
) WITH (
  'connector' = 'print'
);

INSERT INTO sink_table
SELECT
    show_log_table.log_id as s_id,
    show_log_table.show_params as s_params,
    click_log_table.log_id as c_id,
    click_log_table.click_params as c_params
FROM show_log_table
FULL JOIN click_log_table ON show_log_table.log_id = click_log_table.log_id;



-- 输出结果:
+I[null, 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flink SQL中的JOIN操作可以用于实时流处理,实时处理时需要使用Flink的DataStream API将数据流转换为Flink SQL中的Table,并且需要使用Flink的Table API或SQL API执行JOIN操作。 具体的实时JOIN操作步骤如下: 1. 将数据流转换为Table:使用Flink的DataStream API将实时数据流转换为Flink SQL中的Table,可以使用Flink的Table API或SQL API进行操作。例如,可以使用Table API的`fromDataStream`方法将DataStream转换为Table: ``` DataStream<Order> orderStream = ...; Table orderTable = tableEnv.fromDataStream(orderStream); ``` 2. 定义Table Schema:定义Table的结构,包括字段名和数据类型等。这可以通过Table API或SQL API进行定义,例如: ``` Table orderTable = tableEnv.fromDataStream(orderStream, "order_id, user_id, order_total"); ``` 3. 执行JOIN操作:使用Flink SQL中的JOIN操作对Table进行JOIN操作,可以使用Table API或SQL API进行操作。例如,可以使用SQL API的`SELECT`语句进行JOIN操作: ``` String joinSql = "SELECT o.order_id, o.order_total, u.user_name " + "FROM Orders o " + "LEFT JOIN Users u ON o.user_id = u.user_id"; Table joinResult = tableEnv.sqlQuery(joinSql); ``` 4. 输出结果:将JOIN操作后的结果输出到指定的目标位置,可以使用Flink的DataStream API将Table转换为DataStream,并输出到Kafka、MySQL等数据源。 ``` DataStream<Row> joinStream = tableEnv.toAppendStream(joinResult, Row.class); joinStream.addSink(...); ``` 总的来说,Flink SQL中的JOIN操作可以用于实时流处理,可以快速地将多个数据流进行JOIN操作,并输出到指定的目标位置。使用Flink SQL进行实时JOIN操作,可以大大简化代码编写和维护的工作,提高数据处理的效率和准确性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值