Apache Calcite 究竟是干嘛的,又為什么能這么流行呢?
首先,擺一個應該沒多少人會反對的共識:SQL 是編程領域最流行的語言。
- 有 MySQL、Oracle 之類使用 SQL 作為交互語言的數據庫
- 然后有 JDBC、ODBC 之類和各種數據庫交互的標准接口
- 有大量數據科學家和數據分析師等不太會編程語言但又要使用數據的人
- 第一代大數據計算引擎 MapReduce 被 Hive SQL 很大程度上替代
- 新一代大數據計算引擎 Spark 很快就推出了 Spark SQL
- 最近幾年大熱的流處理引擎 Flink 很快也推出了 Flink SQL
- ......
這樣的例子還可以舉出很多。SQL 我們用起來很順手,但實現起來呢,卻並不容易。
比如要給 MongoDB 套上一個 SQL 的殼子,或者要想直接用 SQL 查一堆 CSV 文件,恐怕沒多少人能順利的自己實現。
Apache Calcite 的出現,讓你能夠很容易的給你的系統套上一個 SQL 的殼子,並且能提供足夠高效的查詢性能優化。
下面不會想很多帖子一樣,去解釋 Calcite 是怎么做到這一點的,這樣的東西太多了,沒有必要重復。
今天,我想從設計的角度聊下為什么 Calcite 能這么流行。
足夠簡單和 focus 的定位
通常我們可以把一個數據庫管理系統分為上圖的五個組件。Calcite 在設計之初就確定了自己只關注和實現圖中綠色標識的三個部分,而把灰色部分的數據管理和數據存儲留給了各個外部存儲/計算引擎。
通常數據管理和數據存儲,尤其是后者是很復雜的,也會由於數據本身的特性導致實現上的多樣性。Calcite 拋棄了這兩部分,而是專注於上層更加通用的模塊,使得自己能夠輕裝上陣,系統的復雜性得到控制,開發人員的精力也不至於鋪的太開。
另一方面,Calcite 沒有去重復造各種輪子,在該用現成的東西的時候,就直接用能找到的最合適的。這是個非常好的習慣,但也是非常容易被程序員抵觸的方法。
比如,作為一個 SQL 解決方案,關鍵的 SQL 解析這一步,Calcite 沒有選擇造輪子,而是直接使用了開源的 JavaCC,來將 SQL 語句轉化為 Java 代碼,然后轉化成一顆 AST 供下一階段使用。
另一個例子,為了支持后面會提到的靈活的元數據功能,Calcite 需要支持運行時編譯 Java 代碼。默認的JavaC 太重,需要一個更輕量級的編譯器,Calcite 同樣沒有選擇造輪子,而是使用了開源的 Janino 方案。
足夠簡單和 focus 的定位,不重復造輪子,使得 Calcite 的實現足夠簡單和穩定。
靈活可插拔的架構
上面的圖是 Calcite 官方給出的架構圖。
一方面印證了我們上面提到的,Calcite 足夠簡單,沒有做自己不該做的事;另一方面,也是更重要的,Calcite 被設計的足夠模塊化和可插拔。
JDBC Driver 這個模塊用來支持使用 JDBC client 的應用;SQL Parser and Validator 模塊用來做 SQL 解析和校驗;Expressions Builder 用來支持自己做 SQL 解析和校驗的框架對接;Operator Expressions 這個模塊用來處理關系表達式;Metadata Providers 用來支持外部自定義元數據;Pluggable Rules 用來定義優化規則;最核心的 Query Optimizer 則專注查詢優化。
功能模塊的划分足夠合理,足夠獨立,使得不用完整集成,而是可以只選擇其中的一部分使用;而基本上每個模塊都支持自定義,也使得用戶能更多地定制系統。
通過
- 足夠簡單和focus的定位
- 可插拔的架構
Calcite 做到了讓集成足夠簡單。
通過
- 對多種異構數據源的支持
- 動態和靈活的查詢優化
Calcite 讓自己能在更廣闊的領域被使用。