FLINK SQL JOIN类型
一、REGULAR JOIN
- INNER JOIN:在流处理任务中只用两条流JOIN到才输出,+[L, R]
- LEFT JOIN:在流处理任务中,左流数据到达之后,不管有没有JOIN到右流数据都会输出(JOIN到:+[L, R],没有JOIN:+[L, NULL]),如果右流数据到达之后,发现左流有输出+[L, NULL],则会发起回撤,先输出-[L, NULL],再输出+[L, R]
- RIGHT JOIN:左右流的执行逻辑和LEFT JOIN一样
- FULL JOIN:在流处理任务中,左流或者右流的数据到达之后,无论有没有 Join 到另外一条流的数据,都会输出(对右流来说:Join 到输出 +[L, R],没 Join 到输出 +[NULL, R];对左流来说:JOIN到输出 ,没JOIN到输出+[L, NULL])。如果一条流的数据到达之后,发现之前另一条流之前输出过没有 Join 到的数据,则会发起回撤流(左流数据到达为例:回撤-[NULL, R],输出 +[L, R],右流数据到达为例:回撤-[L, NULL] ,输出+[L, R])
- 测试用例
CREATE TABLE show_log_table( log_id BIGINT, show_params STRING ) WITH ( 'connector' = 'datagen', 'rows-per-second' = '5', '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' = '5', 'fields.click_params.length' = '1', 'fields.log_id.min' = '1', 'fields.log_id.max' = '10' ); SELECT * FROM click_log_table LEFT JOIN show_log_table ON click_log_table.log_id = show_log_table.log_id ; SELECT * FROM click_log_table INNER JOIN show_log_table ON click_log_table.log_id = show_log_table.log_id ; SELECT * FROM click_log_table FULL JOIN show_log_table ON click_log_table.log_id = show_log_table.log_id ;
- 注意:
1)实时REGULAR JOIN支持等值JOIN和不等值JOIN,等值JOIN SHUFFLE策略是HASH,非等值JOIN策略是GLOBAL,所有数据发往一个并发,按照非等值条件进行关联
2)REGULAR JOIN会将两条流的所有数据都存储在 State 中,所以 Flink 任务的 State 会无限增大,因此需要为 State 配置合适的 TTL,以防止 State 过大
二、INTERVAL JOIN
- 时间区间JOIN:让一条流去JOIN另一条流的前后一段时间内的数据,INTERVAL JOIN可以避免回撤流的产生,在某些场景下,下游输出系统不具备处理回撤流的能力,此时可以借助INTERVAL JOIN
- INNER INTERVAL JOIN:只有两条流 JOIN 到(满足ON中的条件:两条流的数据在时间区间 + 满足其他等值条件)才输出,输出 +[L, R]
- LEFT INTERVAL JOIN:流任务中,左流数据到达之后,如果没有JOIN到右流的数据,就会等待(放在 State 中等),如果之后右流之后数据到达之后,发现能和刚刚那条左流数据 JOIN 到,则会输出+[L, R]。事件时间中随着 Watermark 的推进, 如果发现发现左流 State 中的数据过期了,就把左流中过期的数据从 State 中删除,然后输出+[L, R],如果右流 State 中的数据过期了,就直接从 State 中删除
- RIGHT INTERVAL JOIN:处理逻辑和LEFT INTERVAL JOIN类似
- FULL INTERVAL JOIN:流任务中,左流或者右流的数据到达之后,如果没有 Join 到另外一条流的数据,就会等待(左流放在左流对应的 State 中等,右流放在右流对应的 State 中等),如果之后另一条流数据到达之后,发现能和刚刚那条数据 Join 到,则会输出+[L, R]。事件时间中随着 Watermark 的推进(也支持处理时间),发现 State 中的数据能够过期了,就将这些数据从 State 中删除并且输出(左流过期输出 +[L, NULL],右流过期输出 -[NULL, R])
- 案例:
CREATE TABLE show_log_table( log_id BIGINT, show_params STRING, row_time AS cast(CURRENT_TIMESTAMP as timestamp(3)), WATERMARK FOR row_time AS row_time ) WITH ( 'connector' = 'datagen', 'rows-per-second' = '5', '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, row_time AS cast(CURRENT_TIMESTAMP as timestamp(3)), WATERMARK FOR row_time AS row_time ) WITH ( 'connector' = 'datagen', 'rows-per-second' = '5', 'fields.click_params.length' = '1', 'fields.log_id.min' = '1', 'fields.log_id.max' = '10' ); 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_param FROM show_log_table INNER JOIN click_log_table ON show_log_table.log_id = click_log_table.log_id AND show_log_table.row_time BETWEEN click_log_table.row_time - INTERVAL '5' MINUTE AND click_log_table.row_time + INTERVAL '5' MINUTE ;
三、TEMPORARY JOIN
四、LOOKUP JOIN
五、列转行