Flink流計算中SQL表的概念和原理

Android路上的人發表於2018-12-22

前言


Fink在新發布的1.7版本中,不斷完善和加強了SQL&Table API方面的功能支援。這使得在流計算過程中,使用者同樣能夠運用熟悉的SQL語句來做資料處理,查詢。但是相比於窗體的RDBMS而言,流計算過程中的SQL處理難免讓人覺得不是很好理解,畢竟資料不是fixed-sized的,而是連續不斷的。所以本文,筆者來聊聊這個略顯抽象的概念:流計算過程中的表以及SQL查詢的含義。

動態表和動態查詢的概念


在流處理過程中,資料是連續的,所以當我們把這些連續接收到的資料記錄匯聚到一起然後做呈現的時候,它其實是一種“動態”表。當不斷有新的資料來到的時候,這個動態表就不斷擴增。所以動態表在這裡更恰當的比喻應該是一種狀態表資訊。當然鑑於這個表的空間有限(狀態資料儲存受限),後面來的資料要麼會覆蓋早期相同的資料,要麼這個表中過期的資料會被移除。以此維護這個狀態表的資料資訊。當然,在流式計算中,每一條資料都有一個自帶天然屬性的資訊,就是時間,它可以是process time,又或者說是event time。以下是一張歷史訪問頻率動態表的資料內容資訊,它在Flink內部是以State(3個欄位域組成)的形式駐留。

SELECT * FROM RatesHistory;

rowtime currency   rate
======= ======== ======
09:00   US Dollar   102
09:00   Euro        114
09:00   Yen           1
10:45   Euro        116
11:15   Euro        119
11:49   Pounds      108

既然表是動態的表,那也就會有動態的查詢,這裡我們指的一種連續不斷的查詢(Continuous Queries)。針對同樣的查詢條件,因為查詢表的資料是在不斷動態變化的,所以每次連續查詢的結果也將會不同。更進一步地來說,連續查詢的結果我們又可以作為另外一個動態表。最終構成了下圖動態表的處理過程。

在這裡插入圖片描述

再回到前面的動態表概念,這裡的動態表並不會原地更新。它的更新方式是一種append的方式,所以我們會看到Euro的這條記錄有2條。然後當我們程式在查詢這個表的時候,會認為11:15的那條是準確的記錄。但是如果我們帶上時間查詢條件,把時間限定在10~11點之間,那麼Euro的116的那條記錄會是我們想要的結果,比如以下查詢sql。

SELECT *
FROM RatesHistory AS r
WHERE r.rowtime = (
  SELECT MAX(rowtime)
  FROM RatesHistory AS r2
  WHERE r2.currency = r.currency
  AND r2.rowtime <= TIME '10:58');

會查出這樣的結果:

rowtime currency   rate
======= ======== ======
09:00   US Dollar   102
09:00   Yen           1
10:45   Euro        116

同理,我們也可以做這種動態表之間的join操作,這方面詳細內容可參閱文末引用連結處。

動態表的時間屬性


相比較於傳統資料庫表的永續性,動態表的資料具有極強的時效性,也不能夠恆定持有所有的表狀態資料。所以在動態表中,我們要好好利用時間屬性在這裡的作用。如上節提到的,時間屬性是流資料中很關鍵的資訊,我們同樣需要利用這個時間屬性資訊,作為表中的一個關鍵欄位值。比如說,我們完全可以利用動態表做天,小時,甚至分鐘級別內的資料存取、查詢,然後隔天表狀態過期記錄由系統自動清除。這樣我們完全無需藉助外部儲存做來表資料的存放。當然,如果空間足夠,我們可以存放週期更長的表狀態資料,然後做更加完備的查詢處理。這裡其實是資源消耗和準確率之間的一個trade off了。

引用


[1].https://ci.apache.org/projects/flink/flink-docs-master/dev/table/streaming/dynamic_tables.html
[2].https://ci.apache.org/projects/flink/flink-docs-master/dev/table/streaming/temporal_tables.html

相關文章