Flink入坑指南系列文章,從實際例子入手,一步步引導用戶零基礎入門實時計算/Flink,併成長爲使用Flink的高階用戶。本文屬個人原創,僅做技術交流之用,筆者才疏學淺,如有錯誤,歡迎指正。
什麼是view(視圖):
視圖無非就是存儲在數據庫中並具有名字的 SQL 語句,或者說是以預定義的 SQL 查詢的形式存在的數據表的成分。視圖可以包含表中的所有列,或者僅包含選定的列。視圖可以創建自一個或者多個表,這取決於創建該視圖的 SQL 語句的寫法。
視圖,一種虛擬的表,允許用戶執行以下操作:
- 以用戶或者某些類型的用戶感覺自然或者直觀的方式來組織數據;
- 限制對數據的訪問,從而使得用戶僅能夠看到或者修改(某些情況下)他們需要的數據;
- 從多個表中彙總數據,以產生報表。
(引自:極客學院)
Flink SQL兼容標準SQL,view的作用與標準SQL相同,有幾個特點:
- 在Flink SQL中,view是一種臨時表
- 與標準SQL一樣,視圖可以創建自一個或多個表/視圖
- 視圖的結果不會進行持久化,僅作爲計算的中間結果進行傳輸
- 視圖的數據也可以被輸出到結果表中
Flink SQL中,視圖的語法非常簡單,可參考:view語法。接下來我們通過一些例子來實際感受一下視圖的作用。
假設在IoT場景中,要過濾出兩個廠房中的傳感器的異常數據。兩個廠房的數據分別發到了datahub的兩個不同topic,需要將兩個datahub topic中異常數據過濾出來,再彙總。
原始數據結構如下:
- date
- hour
- ip: device ip
- event_id:
DDL -- 定義輸入輸出數據的數據結構,具體語法請參見 datahub源表/結果表語法,維表相關語法詳見Flink SQL維表語法:
-- source1 定義廠房1的topic的數據結構
create table fab1(
`date` int,
hour int,
ip varchar,
event_id BIGINT
) with (
type='datahub',
endPoint='xxxxxxxxx',
project='xxxxxxxxxx',
topic='topic1',
accessId='xXXXXXXXX',
accessKey='XXXXXXXXX');
-- source2 定義廠房2的topic的數據結構
create table fab2(
`date` int,
hour int,
ip varchar,
event_id BIGINT
) with (
type='datahub',
endPoint='xxxxxxxxx',
project='xxxxxxxxxx',
topic='topic2',
accessId='xXXXXXXXX',
accessKey='XXXXXXXXX');
-- 定義結果表1的數據結構
create table sink(
`date` int,
hour int,
event_id bigint,
event_cnt bigint
) with (
type='datahub',
endPoint='xxxxxxxxx',
project='xxxxxxxxxx',
topic='topic2',
accessId='xXXXXXXXX',
accessKey='XXXXXXXXX');
-- 定義結果表2的數據結構
create table sink(
`date` int,
hour int,
event_id bigint,
event_cnt bigint
) with (
type='rds',
url='xxxxxx',
tableName='xxxxxx',
userName='xxxxxx',
password='xxxxxx'
);
-- 維表
CREATE TABLE device_whitelist (
ip varchar,
category varchar,
PRIMARY KEY (ip), -- 用作維表時,必須有聲明的主鍵。
PERIOD FOR SYSTEM_TIME -- 定義維表的變化週期
) with (
type = 'rds',
...
)
寫法一,按照批處理系統/數據庫的思維來看,這個需求非常簡單:
insert into sink
select e.`ip`,e.`hour`,e.`date`,e.`event_id` from
(
select * from fab1
where event_id='00001'
union
select * from fab2
where event_id='00001'
) e
JOIN device_whitelist FOR SYSTEM_TIME AS OF PROCTIME() AS d
ON e.`ip` = d.`ip`
寫法二,使用view,將各個複雜SQL模塊拆開:
--
CREATE VIEW view1(`date`,`hour`,`ip`,`event_id`) AS
SELECT * FROM fab1
WHERE event_id='00001'
UNION
SELECT * FROM fab2
WHERE event_id='00001'
--
CREATE VIEW view2(`date`,`hour`,`ip`,`event_id`) AS
SELECT e.`date`,e.`hour`,e.`ip`,e.`event_id` FROM view1 e
JOIN device_whitelist FOR SYSTEM_TIME AS OF PROCTIME() AS d
ON e.`ip` = d.`ip`
-- INSERT INTO sink1
INSERT INTO sink1
SELECT * FROM view2
-- INSERT INTO sink2
INSERT INTO sink2
SELECT * FROM view1
Flink中SQL的數據是不斷動態變化的,特別是涉及到一些特殊語法(如window級連/嵌套等),需要分步調試每個SQL模塊的結果。如果用寫法一,會大大增加SQL調試難度。因此,使用Flink SQL,建議使用第二種寫法,用view將各個語法塊串聯,方便調試和排查問題。寫法一和寫法二最終生成的作業DAG圖都是一樣的,沒有任何區別。一個Flink SQL作業可以同時定義多個輸出表,結果可同時被輸出到多種數據源中。
如果在使用實時計算產品過程中有任何問題,歡迎在博客下方回覆交流。