Flink Windows Join 都是 Inner Join
兩個流join時,先做join操作,形成JoinedStream,然後再指定Window,最後接着join後的transform操作。
案例:
inputStream1:DataStream[(Long,String,Int)] = ...
inputStream2:DataStream[(String,Long,Int)] = ...
//通過DataStream Join方法將兩個數據流關聯
inputStream1.join(inputStream2)
//指定inputStream1的關聯Key
.where(_._1)
//指定inputStream2的關聯Key
.equalTo(_._2)/
//指定Window Assigner
.window(TumblingEventTimeWindows.of(Time.milliseconds(10)))
.apply(<JoinFunction>) //指定窗口計算函數
根據窗口的不同,數據計算的方式不同
根據窗口的選擇,依次對應於:
滾動窗口關聯:Tumbling Window Join
滑動窗口關聯:Sliding Window Join
會話窗口關聯:Session Window Join
間隔關聯:Interval Join
間隔關聯 Join
間隔關聯與其他窗口關聯不同,間隔關聯的數據元素關聯範圍不依賴窗口劃分,而是通過DataStream元素的時間加上或減去指定Interval作爲關聯窗口,然後和另外一個DataStream的數據元素時間在窗口內進行Join操作。
示例代碼:
//創建黑色元素數據集
val blackStream: DataStream[(Int, Long)] = env.fromElements((2, 21L), (4, 1L), (5, 4L))
//創建白色元素數據集
val whiteStream: DataStream[(Int, Long)] = env.fromElements((2, 21L), (1, 1L), (3, 4L))
//通過Join方法將兩個數據集進行關聯
val windowStream: DataStream[String] = blackStream.keyBy(_._1)
//調用intervalJoin方法關聯另外一個DataStream
.intervalJoin(whiteStream.keyBy(_._1))
//設定時間上限和下限
.between(Time.milliseconds(-2), Time.milliseconds(1))
.process(new ProcessWindowFunciton())
//通過單獨定義ProcessWindowFunciton實現ProcessJoinFunction
class ProcessWindowFunciton extends ProcessJoinFunction[(Int, Long), (Int, Long), String] {
override def processElement(in1: (Int, Long), in2: (Int, Long), context: ProcessJoinFunction[(Int, Long), (Int, Long), String]#Context, collector: Collector[String]): Unit = {
collector.collect(in1 + ":" + (in1._2 + in2._2))
}
}
Flink SQL Join
經典的Join算法-歸併連接算法
經典的Join算法-哈希連接算法
Flink 流式SQL - 普通連接Join
對於不帶窗口的全量連接,內部Join算子,會維護A、B兩張表的哈希索引。當A表中插入一條數據時會查B的索引,尋找Join的條件數據,同時將本條數據加入A的索引。反之亦然。但是這種join會隨着數據量的增加,哈希表維護成本可能會無限增長下去。
解決方式是通過狀態TTL等手段加以限制。