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

 

五、列转行

posted @ 2022-03-01 15:19  Shydow  阅读(1779)  评论(0编辑  收藏  举报