Flink Table API/SQL 是如何變成程序運(yùn)行的
本文轉(zhuǎn)載自微信公眾號「KK架構(gòu)師」,作者wangkai。轉(zhuǎn)載本文請聯(lián)系KK架構(gòu)師公眾號。
一、Flink Api 的分層抽象
如上圖,最下面一層是 Process Function ,可以去做一些有狀態(tài)的計(jì)算,注冊 Timer 定時器,可以做更復(fù)雜的操作,靈活性更高,可以做非常復(fù)雜的定制開發(fā);
第二層是 DataStream Api,基于 Process Function,封裝了很多的操作。比如可以方便做一個 KeyBy 操作 + Window 的聚合;
最上面一層是 關(guān)系型 Api,是在 DataStream Api 之上的更高級的抽象,我們可以借助 SQL 這種非常經(jīng)典的穩(wěn)定的語言,來構(gòu)建實(shí)時流程序。
二、為什么要提供 Table Api 和 SQL?
1. 開發(fā)繁瑣
DataStream Api / Process Function 更加面向的是開發(fā)者,想要開發(fā)出合理的 Flink 程序,至少需要具備以下技能:
- 具有 Java 、Scala 開發(fā)經(jīng)驗(yàn);
- 需要對 Time、State 以及 Window 等流式概念有非常深入的了解;
- 具有分布式處理的經(jīng)驗(yàn)和知識;
- 具有作業(yè)調(diào)優(yōu)的經(jīng)驗(yàn);
這樣的話,對數(shù)據(jù)分析人員和業(yè)務(wù)人員很不友好,使用起來學(xué)習(xí)成本非常高,望塵莫及。
并且開發(fā)起來非常繁瑣,開發(fā)應(yīng)用需要使用 Function 接口,即使是一個簡單的過濾也要實(shí)現(xiàn)一個 FilterFunction 匿名類,而使用 Table Api 則簡單很多。
2. 代碼不通用
Table Api 和 SQL 是流批通用的,代碼完全可以復(fù)用。不必流式程序使用 DataStream Api,批處理使用 DataSet Api (注:社區(qū)未來可能會廢棄 Dataset Api,統(tǒng)一使用 DataStream Api 來開發(fā)批流程序)。
3. 框架很難優(yōu)化
在使用 DataStream Api 和 DataSet Api 開發(fā)應(yīng)用的時候,F(xiàn)link 框架只能進(jìn)行非常有限的優(yōu)化,需要開發(fā)者非常謹(jǐn)慎的編寫高效的應(yīng)用程序。
而使用 Table Api 或 SQL,則可以使用 Calcite 的 SQL 優(yōu)化器,更容易寫出執(zhí)行效率高的應(yīng)用。
二、Table Api / SQL 是如何轉(zhuǎn)換為程序運(yùn)行的?
如下圖所示
SQL 執(zhí)行被分成兩個大的階段,從 SQL 語句到 Operation,從 Operation 到 Transformation,然后就進(jìn)入分布式執(zhí)行的階段。
1. 前置知識:Apache Calcite
Apache Calcite 是個動態(tài)數(shù)據(jù)管理框架,具備很多數(shù)據(jù)庫管理系統(tǒng)的功能,如 SQL 解析,SQL 校驗(yàn),SQL 查詢優(yōu)化,SQL 生成以及數(shù)據(jù)連接查詢等,但是并不存儲元數(shù)據(jù)和基本數(shù)據(jù),不包含處理數(shù)據(jù)的算法。
由于舍棄了這些功能,Calcite 可以在應(yīng)用和數(shù)據(jù)存儲,數(shù)據(jù)處理引擎之間很好的扮演中介的角色。
它不受上層編程語言的限制,前端可以使用 SQL、Pig、Cascading 等語言,只要通過 Calcite 提供的 SQL Api 將它們轉(zhuǎn)化成關(guān)系代數(shù)的抽象語法樹即可,并根據(jù)一定的規(guī)則和成本對抽象語法樹進(jìn)行優(yōu)化,最后推給各個數(shù)據(jù)處理引擎來執(zhí)行。
所以 Calcite 不涉及物理規(guī)劃層,它通過擴(kuò)展適配器來連接多種后端的數(shù)據(jù)源和數(shù)據(jù)處理引擎,如 Hive,Drill,F(xiàn)link,Phoenix。
2. SQL 語句到 Operation 過程
首先使用 Calcite 對 SQL 語句進(jìn)行解析,獲取 SQL Node,再根據(jù)不同的 SQL 類型分別進(jìn)行轉(zhuǎn)換,校驗(yàn)語法的合法性,再根據(jù)語句類型(DQL、DML、DDL)轉(zhuǎn)換成對應(yīng)的算子樹。
對于 SQL 查詢語句而言,會轉(zhuǎn)換為 QueryOperation 樹。
3. Operation 到 Transformation 過程
首先 Operation 先轉(zhuǎn)換為 Calcite 的邏輯計(jì)劃樹,再對應(yīng)地轉(zhuǎn)換為 Flink 的邏輯計(jì)劃樹,然后進(jìn)行優(yōu)化。
優(yōu)化后的邏輯樹轉(zhuǎn)換為 Flink 的物理計(jì)劃,然后物理計(jì)劃通過代碼生成算子、UDF、表達(dá)式等代碼,包裝到 Transformation 中,形成 Transformation 流水線,再轉(zhuǎn)換為 StreamGraph ,最終就可以提交到 Flink 集群真正運(yùn)行起來了。
(后面會專門寫源碼分析的文章,來重點(diǎn)講述這兩部分的內(nèi)容,持續(xù)關(guān)注我)
4. 元數(shù)據(jù)
元數(shù)據(jù)是是 Flink SQL 處理數(shù)據(jù)非常重要的一個部分,元數(shù)據(jù)描述了 Flink 處理的讀取和寫出的數(shù)據(jù)的結(jié)構(gòu)以及數(shù)據(jù)的訪問方法等信息,沒有元數(shù)據(jù),F(xiàn)link 就無法對 SQL 進(jìn)行校驗(yàn)和優(yōu)化了。
元數(shù)據(jù)包含以下信息:
- 庫
- 表
- 視圖
- UDF
- 表字段
如上圖所示,在 Flink 中,Catalog 是元數(shù)據(jù)的核心抽象,目前 Flink 實(shí)現(xiàn)了內(nèi)存小 GenericMemoryCatalog 和 HiveCatalog 兩種 Catalog。
5. 優(yōu)化器
SQL 查詢優(yōu)化是來自數(shù)據(jù)庫系統(tǒng)的概念,查詢優(yōu)化器是關(guān)系型數(shù)據(jù)庫管理系統(tǒng)的核心之一,決定對特定的查詢使用哪些索引、哪些關(guān)聯(lián)算法,從而使 SQL 高效運(yùn)行。
SQL 優(yōu)化器很大程度上決定了一個系統(tǒng)的執(zhí)行性能。
查詢優(yōu)化器分成兩類,基于規(guī)則的優(yōu)化器(Rule-Based Optimizer,RBO)和基于代價的優(yōu)化器(Cost-Based Optimizer,CBO)。
RBO 規(guī)則優(yōu)化,主要就是等價改變查詢語句的形式,以便產(chǎn)生更好的邏輯執(zhí)行計(jì)劃,比如重寫用戶的查詢(謂詞推進(jìn),物化視圖重寫,視圖合并等),然后還需要將邏輯執(zhí)行計(jì)劃變成物理執(zhí)行計(jì)劃。
CBO 代價優(yōu)化,除了做上述 RBO 的規(guī)則優(yōu)化外,還會通過復(fù)雜的算法統(tǒng)計(jì)信息,統(tǒng)計(jì)各個執(zhí)行計(jì)劃的執(zhí)行成本,從不同的執(zhí)行計(jì)劃中選擇出執(zhí)行代價最小的一個計(jì)劃,轉(zhuǎn)換為 Flink 的執(zhí)行計(jì)劃。
三、總結(jié)
Flink Table Api / SQL 提供了對用戶友好的接口來更高效的完成實(shí)時流式程序的開發(fā)。
Flink 依托 Apache Calcite 提供的 SQL 解析、優(yōu)化框架,解析構(gòu)建為邏輯計(jì)劃樹,通過 Planner 層層優(yōu)化為 Flink 可以運(yùn)行的內(nèi)部結(jié)構(gòu),最終提交到 Flink 集群上運(yùn)行。