在 CloudQuery 採用 Apache Arrow
已發布 2023 年 5 月 4 日
作者 Yevgeny Pats
這篇文章是與 CloudQuery 合作撰寫,並同步發布在 CloudQuery 部落格。
CloudQuery 是一個以 Go 語言撰寫的高效能開源 ELT 框架。我們先前討論過一些為了建構高效能 ELT 框架而採取的架構和設計決策。類型系統是建立高效能且可擴展 ELT 框架的關鍵組件,其中來源和目的地是解耦的。在這篇部落格文章中,我們將深入探討為何我們決定採用 Apache Arrow 作為我們的類型系統,並替換我們內部的實作。
什麼是類型系統?
讓我們快速回顧一下什麼是類型系統,以及為什麼 ELT 框架需要類型系統。從非常高的層次來看,ELT 框架從某些來源提取數據,並以特定的模式將其移動到某些目的地。
API ---> [Source Plugin] -----> [Destination Plugin]
-----> [Destination Plugin]
gRPC
來源和目的地是解耦的,並透過 gRPC 進行通訊。這對於允許新增新的目的地和更新舊的目的地至關重要,而無需更新來源外掛程式碼(否則會引入無法維護的架構)。
這就是類型系統的用武之地。來源外掛程式以盡可能高效能的方式從 API 提取資訊,定義模式,然後將來自 API 的結果(JSON 或任何其他格式)轉換為定義完善的類型系統。然後,目的地外掛程式可以輕鬆地為其資料庫建立模式,並將傳入的資料轉換為目的地類型。因此,總而言之,來源外掛程式主要向目的地發送兩件事:1) 模式 2) 符合已定義模式的記錄。在 Arrow 術語中,這些是模式和記錄批次。
為什麼選擇 Arrow?
在 Arrow 之前,我們使用自己的類型系統,該系統支援超過 14 種類型。這對我們來說運作良好,但我們開始在各種使用案例中遇到限制。例如,在資料庫到資料庫的複製中,我們需要支援更多類型,包括巢狀類型。此外,就效能而言,ELT 流程中花費的大量時間都用於將資料從一種格式轉換為另一種格式,因此我們想退一步看看是否可以避免這個著名的 XKCD(透過建立另一種格式)。

這就是 Arrow 的用武之地。Apache Arrow 定義了一種與語言無關的欄狀格式,用於平面和階層式資料,並帶來以下優勢:
- 跨語言且具有適用於不同語言的廣泛函式庫 - 格式透過 flatbuffers 定義,以便您可以使用任何語言解析它,並且已經在 C/C++、C#、Go、Java、JavaScript、Julia、Matlab、Python、R、Ruby 和 Rust 中獲得廣泛支援(在撰寫本文時)。對於 CloudQuery 而言,這非常重要,因為它使得以不同語言開發來源或目的地外掛程式變得更加容易。
- 效能:Arrow 的採用正在興起,尤其是在基於欄狀的資料庫 (DuckDB、ClickHouse、BigQuery) 和檔案格式 (Parquet) 中,這使得為已經支援 Arrow 的資料庫編寫 CloudQuery 目的地或來源外掛程式變得更容易,並且效率更高,因為我們消除了對額外序列化和轉換步驟的需求。此外,僅僅是從來源外掛程式向目的地發送 Arrow 格式的效能就已經更高且記憶體效率更高,因為它具有「零複製」特性,並且不需要序列化/反序列化。
- 豐富的資料類型:Arrow 支援超過 35 種類型,包括複合類型(即所有可用類型的列表、結構和映射)以及使用自訂類型擴展類型系統的能力。此外,已經存在從/到 arrow 類型系統和 parquet 類型系統的內建映射(包括巢狀類型),這已經在許多 arrow 函式庫中支援,如此處所述。
總結
採用 Apache Arrow 作為 CloudQuery 的記憶體類型系統使我們能夠獲得更好的效能、資料互操作性和開發人員體驗。一些將立即獲得豐富類型系統提升的外掛程式是我們的資料庫到資料庫複製外掛程式,例如 PostgreSQL CDC 來源外掛程式(以及所有 資料庫目的地),這些外掛程式將獲得對所有可用類型(包括巢狀類型)的支援。
我們對這一步感到興奮,並加入不斷成長的 Arrow 社群。我們已經貢獻了超過 30 個上游提取請求,這些請求已由 Arrow 維護者快速審查,謝謝!