Calcite在大資料系統中有著廣泛的運用, 比如Apache Flink, Apache Drill等都大量使用了Calcite,理解Calcite的原理可以說已經成為理解大資料系統中SQL訪問層實作原理的必備條件之一,
但是不少人在學習Calcite的程序中都發現關于Calcite的實踐案例其實很少,本文就將為大家詳細介紹如何基于Calcite框架的SQL語法擴展探索使之更符合你的業務需求,以及擴展SQL在數堆疊產品的應用實踐,
Calcite介紹及用途
Calcite介紹
Apache Calcite是一個動態的資料管理框架,本身不涉及任何物理存盤資訊,而是專注在SQL決議、基于關系代數的查詢優化,通過擴展方式來對接底層存盤,
目前Apache Calcite被應用在廣泛的資料開源系統中,比如Apache Hive、Apache Phoenix、Apache Flink等,

Calcite的用途
Calcite提供了ANSI標準SQL的決議,以及各種SQL 方言,針對來自于不同資料源的復雜SQL,在Calcite中會把SQL決議成SqlNode語法樹結構,然后根據得到的語法樹轉換成自定義Node,通過自定義Node決議獲取到表的欄位資訊、以及表資訊、血緣等相關資訊,
下圖展示了一部分對外提供的介面資訊:

sqlparser 決議模塊主要提供了以下幾種功能 :
? 決議SQL包含的所有表、欄位資訊
? 決議SQL的udf函式
? 決議SQL的血緣資訊,包括表級血緣、欄位血緣
? 決議自定義SqlNode
? api服務變數決議替換
SQL語法擴展
了解完Calcite是什么以及用途后,下面為大家分享Calcite SQL語法擴展的相關內容,
SQL語法擴展背景
在 sqlparser 中進行sql決議的場景中,有兩種情況需要使用到自定義擴展,一是Calcite不支持的一些語法;二是在一些場景中存在sql中帶有${var}自定義變數語法,
那么針對上面的這兩種情況,Calcite的自定義擴展是如何實作的呢?自定義擴展主要涉及到以下三個檔案:
? Parser.jj:Parser.jj是一個Calcite核心的語法和詞法檔案,基于Apache FreeMaker模版,該模版包含著變數,這些變數在編譯時可以被替換
? parserImpl.ftl:提供自定義SQL陳述句、literals、dataType的實作方法
? config.fmpp:該檔案是FMPP的組態檔,提供了SQL陳述句、literals、dataType的介面擴展入口
Calcite使用javacc作為語法決議器,freemaker作為模版,把parserImpls.ftl、config.fmpp、Parser.jj模版合成最終的語法詞法檔案,最終通過javacc編譯成自定義的決議器原始碼,整體流程如下圖所示:

擴展SQL實作
● 工程目錄

● 擴展sql實作案例
支持以下limit相關語法以及數字可以寫成${var}形式:
-> limit count, limit start count
-> limit count offset start
-> offset start limit count
在原生的Calcite決議是支持limit count語法的,但是由于回傳SqlOrderBy物件內部類Operator的unparse方法在SQL輸出程序中對原始SQL進行了改寫,因此需要使用擴展SQL得到正確的SQL,
下面介紹一個limit offset語法擴展樣例,擴展SQL如下:
select id, name from test where id > 3 order by id desc limit 1 offset ${offset_val}
整體流程如下:
01
Parser.jj 定義${var}變數的token詞法DOLLAR_VARIABLE:

02
Parser.jj 擴展的變數方法接入,下面方法會在決議到limit、offset關鍵字后面的一個詞時進行呼叫:

03
Parser.jj limit offset在select語法的核心處理邏輯:
-> 定義變數

主要定義了三個boolean型別的變數,isOffsetLimit表示offset limit 語法,isLimitOffset表示limit offset語法,isOnlyLimit表示limit count、limit start count語法,
-> 定義處理邏輯

-> 回傳自定義SqlNode

針對符合上面的三個boolean條件時,使用自定義ExtendSqlOrderBy的擴展類,
04
parserImpl.ftl 定義擴展的SqlNode ExtendDollarVariable:

05
config.fmpp 定義包以及擴展實作類的import:

06
擴展SqlNode實作:
-> 變數實作sqlNode

-> 擴展limit實作類ExtendSqlOrderBy,該類實作了SqlOrderBy,并在此基礎擴展了limit的SqlNode,以及isOffsetLimit、isLimitOffset、isOnlyLimit三個boolean標識limit的不同語法


通過上面的這些步驟后,最后決議生成的SqlNode語法樹如下所示:

擴展SQL在數堆疊的應用
目前袋鼠云的底層sqlparser sql決議涉及的子產品應用包括API資料服務、離線開發、客戶資料洞察(標簽)、實時開發等,雖然大部分針對Calcite的SQL語法擴展相對于上層的產品應用感知不是很明顯,但是擴展SQL還是解決了一些痛點,主要如下:
? 逐漸替換底層采用了多種決議工具決議的情況,使維護更簡單,減少bug的產生
? 解決一些不支持的語法,避免在上層業務層做處理或者在底層做一些特殊處理
以在API資料服務后續接入的like語法改造為例為大家進行分享,目前的API資料服務中支持like ${var}語法,在執行測驗中通過傳遞like語法來確定執行的模糊匹配方式,例如%xx、xx%、%xx%,
收到客戶提出的優化like語法場景,袋鼠云本著客戶第一的原則,這種合理的優化需求是采納的,SQL支持like%${var}、${var}%、%${var}%,這樣在執行測驗中就不需要輸入%了,目前擴展SQL語法已經支持這種優化的like語法,預計在2023年上半年會接入進去,下面通過API資料服務展示當前like SQL和擴展后的SQL差異:
● 當前like ${var}處理
-> 生成API

-> 測驗執行,模糊匹配需要輸入%

● 擴展like %${var}%
-> 生成API

-> 測驗執行,由于在SQL階段已經寫了模糊匹配方式,因此可以直接輸入值

總結規劃
相信通過上面的案例后,大家對于Calcite擴展SQL語法的流程應該有了大致的了解,目前在袋鼠云的業務場景中已經擴展了許多語法,在未來還有一些作業需要進行優化:
? 豐富SQL語法,實作不同資料源擴展SQL語法的隔離
? 逐漸通過SQL語法擴展替換掉底層Calcite和druid共同決議的場景,避免維護多套相同的決議,減少線上問題產生
最后如果是初步接觸Calcite SQL語法擴展的同學們,建議先熟悉javacc語法,
地址:https://javacc.github.io/javacc/
想了解或咨詢更多有關袋鼠云大資料產品、行業解決方案、客戶案例的朋友,瀏覽袋鼠云官網:https://www.dtstack.com/?src=https://www.cnblogs.com/DTinsight/p/szbky
同時,歡迎對大資料開源專案有興趣的同學加入「袋鼠云開源框架釘釘技術qun」,交流最新開源技術資訊,qun號碼:30537511,專案地址:https://github.com/DTStack
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/541902.html
標籤:大數據
上一篇:Mysql頁分裂
