數據倉庫如何實現湖倉一體數據分析?

一. 背景

隨着雲計算的普及和數據分析需求的擴大,數據湖+數據倉庫的湖倉一體分析能力成爲下一代數據分析系統的核心能力。相對於數據倉庫,數據湖在成本、靈活性、多源數據分析等多方面,都有着非常明顯的優勢。IDC發佈的十項2021年中國雲計算市場趨勢預測中,有三項和數據湖分析有關。可以預見,跨系統集成能力、數據控制能力和更加全面的數據驅動能力,將會是未來數據分析系統重要的競爭領域。

AnalyticDB PostgreSQL版(簡稱ADB PG)是阿里雲數據庫團隊基於PostgreSQL內核(簡稱PG)打造的一款雲原生數據倉庫產品。在PB級數據實時交互式分析、HTAP、ETL、BI報表生成等業務場景,ADB PG都有着獨特的技術優勢。作爲一個數據倉庫產品,ADB PG是如何具備湖倉一體分析能力呢?本文將會介紹ADB PG如何基於PG外表、打造數據湖分析能力。

ADB PG繼承了PG的外表(Foreign Table)功能,目前ADB PG的湖倉一體能力主要是基於外表打造的。基於PG外表,ADB PG可以對其他數據分析系統的數據進行查詢和寫入,在兼容多種數據源的同時,複用ADB PG原有的優化器和執行引擎優勢。ADB PG的湖倉一體分析能力目前已經支持OSS、MaxCompute、Hadoop、RDS PG、Oracle、RDS MySQL等多種數據源的分析或者寫入。用戶可以靈活地將ADB PG應用於數據存儲、交互式分析、ETL等不同領域,可以在單個實例中實現多種數據分析功能。即可以用ADB PG完成數據分析的核心流程,也可以作爲衆多環節中的一環去搭建數據鏈路。

不過,外表數據的分析依賴於外部SDK和網絡IO來實現數據讀寫,由於網絡本身的特性與本地磁盤有巨大差異,因此需要在技術層面與本地存儲不同、需要不同的性能優化方案。本文以OSS外表數據讀寫爲例,介紹ADB PG在構建湖倉一體分析能力時,所遇到的一些重要問題和解決方案。

二. 問題分析

ADB PG內核可以分爲優化器、執行引擎和存儲引擎。外表數據分析可以複用ADB PG原有的優化器和執行引擎的核心部分,僅需少量修改。主要擴展是存儲引擎層的改造,也就是通過外表接口對外表數據進行讀寫。外表數據是存儲在另一個分佈式系統當中,需要通過網絡與ADB PG進行連接,這是和讀取本地文件的最核心的區別。一方面,不同的外表數據會提供不同的遠程訪問接口,需要在工程上進行兼容,比如OSS、MaxCompute的數據讀取接口都不相同。另一方面,通過網絡訪問遠程機器上的數據有一定的共性,比如網絡的延遲、網絡放大、帶寬限制、網絡穩定性問題等。

本文將會圍繞上述核心挑戰,介紹ADB PG外表分析項目在支持OSS數據分析過程中的一些重要技術點。OSS是一種阿里雲推出的一種低成本分佈式存儲系統,存儲了大量的冷熱數據,有較大的數據分析需求。爲了方便開發者進行擴展,OSS提供了基於Java、Go、C/C++、Python等主流開發語言的SDK。ADB PG採用了OSS C SDK進行開發。目前ADB PG已經完美支持OSS外表分析的各項功能,除建表語句不同外,用戶可以像訪問本地表一樣訪問OSS外表。支持併發讀取和寫入,支持CSV、ORC、Parquet等常見數據格式。

三. 外表分析技術優化

接下來,我們介紹ADB PG在基於OSS C SDK開發OSS外表分析過程中,解決的一些核心技術問題。

3.1 網絡碎片請求問題

在分析型數據庫場景,業界普遍認爲列式存儲在IO性能上強於行式存儲。因爲列式存儲在掃描數據時,只需要掃描特定列,而行式存儲畢竟掃描全量數據,因此列式存儲可以節約一些IO資源。但是在開發過程中,團隊發現在一些場景下,如字段較多的大寬表掃描,掃描性能較高的列存格式竟然比掃描CSV行存文本格式性能還要差。後經過定位發現一方面掃描ORC/PARQUET 格式時,客戶端與OSS服務端交互次數過於頻繁,另一方面ADB PG單次向OSS請求的數據量比較小。這兩個原因帶來了很大的性能問題。

我們知道,相比於本地磁盤IO,網絡IO所產生的往返時延往往可以放大幾個量級。因此,如果解析一些列存格式(如ORC/PARQUET)時,如果將網絡請求當作本地磁盤請求處理,高壓縮比所帶來的網絡帶寬佔用的減少不足以抵消碎片化請求帶來的往返時延放大,因此性能測試結果低於預期。問題的解決方案,就是通過緩存來減少碎片化的網絡請求。ADB PG每次掃描OSS數據都會“預加載”足夠的數據並緩存,請求時,判定是否命中緩存,如果命中,則直接返回緩存;否則,繼續下一輪次的“預加載”,從而降低網絡請求次數,提高單次請求效率。“預加載”的緩存大小開放配置,默認大小爲1MB。

3.2 列過濾與謂詞下推

由於網絡本身的IO性能往往是低於本地存儲的IO性能的,因此在掃描外表數據時,要儘量減少IO的帶寬資源消耗。ADB PG在處理ORC、Parquet格式的文件時,採用了列過濾和謂詞下推技術,來達到這一目的。

列過濾,即外表只請求SQL查詢所需的數據列、忽略不需要的數據列。因爲ORC、Parquet都是列式存儲格式,所以外表在發起網絡請求時,只需請求所需列所在的數據範圍即可,從而大幅減小網絡I/O。同時,ORC、Parquet會對列數據進行壓縮處理,進一步減小I/O。

謂詞下推,是將執行計劃裏的上層的過濾條件(如WHERE子句中的條件),移動到下層的外表掃描節點,使外表掃描進行網絡請求時,過濾掉不符合查詢條件的數據塊,從而減少網絡I/O。在ORC/Parquet格式文件中,會在每一個block頭部保存該block中每一列數據的min/max/sum等統計信息,當外表掃描時,會先讀取該block的頭部統計信息,與下推的查詢條件進行比較,如果該列的統計信息不符合查詢條件,則可以直接跳過該列數據。

這裏簡單介紹ORC格式的外表的謂詞下推的實現方案。一個ORC文件按數據行分成若干個Stripe組成,Stripe中數據按列式存儲。每個Stripe又分爲若干個Row Group, 所有列的每10000行 組成一個Row Group。如下圖所示。

ORC文件保存3個層次的統計信息,文件級別與Stripe級別的統計信息存儲在ORC文件末尾,Row Group級別的統計信息在每個Stripe塊頭部存放。使用這3個層次的統計信息,ORC外表可以實現文件級過濾,Stripe級過濾以及Row Group級別過濾。具體做法是,每當掃描一個新的ORC文件,會先讀取文件末尾的文件級統計信息,若不符合查詢條件,則直接跳過整個文件的掃描;接着讀取文件末尾所有Stripe級別的統計信息,過濾掉不符合條件的Stripe塊;對於每個符合條件的Stripe塊,讀取塊頭部的Row Group 級別的統計信息,過濾掉不必要的數據。

3.3 “996”問題

OSS C SDK定義了一類錯誤代碼,用於表示異常情況,這裏的996是OSS C SDK中定義的錯誤碼-996。類似的還有錯誤碼-998、-995、-992等。這一類錯誤,通常都是網絡異常導致的OSS外表導入導出失敗。-996是最爲常見的一種。

OSS C SDK內部使用CURL與OSS服務端進行網絡交互,相應的CURL錯誤碼,常見CURL 56(Connection reset by peer)、52等。這些網絡異常,通常是由於OSS服務端在負載較高情況下,服務端主動剔除其認爲“不活躍”的客戶端連接所致。當需要導入或導出較大規模OSS數據時,由於客戶端處於執行計劃的不同階段,不能長時間持有連接進行連續通信,從而被OSS服務端當作“不活躍”的客戶端連接而關閉。

通常對於這種情況,客戶端需要嘗試重試解決。實際開發過程中發現,即使客戶端接口增加了自動異常重試機制,這種異常依然得不到改善。後經過定位發現,OSS C SDK爲提高連接效率,增加了CURL句柄的連接池,但這些網絡異常的CURL句柄,也會存放到池中,因此,即使重試,還是會使用異常的CURL句柄進行通信,所以996異常的問題得不到改善。

既然知道了根本原因,解決的方法也很直觀。我們在CURL句柄的回收接口中,增加對CURL句柄狀態檢查,對於異常的CURL句柄進行銷燬,而不是加回連接池中。這樣避免了連接池中存在無效的CURL句柄。客戶端接口重試時,選擇有效的或者創建新的CURL連接再次通信即可。當然,自動異常重試機制只能針對那些可以重試解決的情況。

① ADB PG訪問OSS外表時,先從CURL連接池中獲取連接,若不存在則新建。

② ADB PG使用CURL連接句柄與OSS Server請求通信。

③ OSS Server通過CURL連接句柄返回通信結果。

④ 正常返回的CURL連接句柄使用完畢後加回連接池待下次使用。

⑤ 異常狀態的CURL連接句柄銷燬。

3.4 內存管理方案的兼容問題

ADB PG基於PostgreSQL內核打造,也繼承了PostgreSQL的內存管理機制。PostgreSQL的內存管理採用了進程安全的內存上下文MemoryContext,而OSS C SDK是線程安全的內存上下文APR Pool。在MemoryContext內存環境下,每個已經分配的內存,都可以顯式的調用free釋放,由MemoryContext進行內存碎片的整理,但在APR Pool中,我們只看到內存池的創建、內存的申請和內存池的銷燬等操作,卻沒有內存的顯式釋放接口。

這種情況意味着,我們需要對於OSS C SDK接口所持有的內存的生命週期有明確的瞭解,否則極易出現內存泄漏和訪問已經釋放的內存等問題。通常我們會按照如下兩種方式申請APR Pool的內存。

  • 方式一適用於重入低頻的操作接口,如獲取OSS文件清單列表。
  • 方式二適用於多次重入的操作接口,如週期性向OSS請求指定文件指定範圍的數據。

通過這種方法,可以很好地解決ADB PG與OSS C SDK在內存管理方面的不兼容問題。

3.5 數據格式的兼容和優化

OSS上的數據,大部分採用CSV、ORC、Parquet等格式。由於ORC/Parquet等格式對數據的底層存儲編碼,與ADB PG的數據編碼並不一致,所以當進行外表掃描時,數據類型轉換是必不可少的步驟。類型轉換,本質上是將數據從一種編碼,改變成另一種編碼方式。例如ORC對於Decimal類型的表示方式和ADB PG不相同,在ORC中Decimal64類型由一個int64存放數據的數字值,再由precision和scale表示數字個數和小數點位數,而在ADB PG中, Decimal類型由int16 數組來存放數據的數字值。格式轉換算法需要對每個數據進行循環的除法與取模操作,這是非常耗費CPU的。

爲了減少類型轉換帶來的CPU消耗,進一步優化外表查詢性能,ADB PG在使用外表進行導出數據時,跳過類型轉換步驟,直接將ADB PG的數據,以二進制形式寫入到外表文件中,這樣在查詢外表時,也無需進行任何數據類型轉換。例如,在導出ORC外表時,外表可以將任意的數據類型,都直接寫入爲ORC的Binary類型,在ORC中存儲的二進制數據,都是按照對應ADB PG的數據類型來編碼,於是在查詢該ORC外表時,可以直接省略類型轉換步驟,減少了CPU消耗。根據TPCH查詢測試結果,整體查詢性能可以提升15%-20%左右。

四. 性能測試

關於在ADB PG中如何使用外表分析功能,請參考阿里雲產品手冊(https://help.aliyun.com/document_detail/164815.html?spm=a2c4g.11186623.6.602.78db2394eaa9rq)。除建表語句不同外,對外表的操作和對本地表的操作幾乎沒有區別,學習難度很低。我們在這裏對比一下OSS外表分析場景,與本地表分析場景的性能問題。

環境配置。我們測試採用的機器是阿里雲ECS d1ne.4xlarge機型,單機配置16個Intel Xeon E5-2682v4核心、64GB內存,每臺ECS配置4塊HDD本地磁盤,每塊盤讀寫速度約200MB/s。測試一共用了4臺ECS,兩臺用於做Master節點、4臺用於做Segment節點,共部署16個segment。本次測試使用的是TPCH查詢,使用了官方工具生成的1TB數據集。

本地表我們測試了經過壓縮的列存表(AOCS)和HEAP表兩種格式, OSS外表我們測試了CSV、ORC、Parquet和JSON四種格式。TPCH 22條查詢的總執行時間見下表。從測試數據可以看出,兩種本地表中,AOCS表的查詢性能略優於HEAP表。外表方面,CSV格式、ORC格式和Parquet格式的外表查詢性略慢於本地表的查詢性能,差距在50%左右。JSON格式的外表查詢性能明顯慢於其他格式,這主要是由於JSON格式本身解析速度慢導致的,與外表無關。

下圖是TPCH 22條查詢的詳細時間。本地表與外表的性能差距在不同的查詢上差距有所不同。考慮到外表在存儲成本、靈活性、擴展能力方面的優勢,ADB PG外表分析在應用場景的潛力是巨大的。

五. 總結

湖倉一體是下一代數據倉庫產品的一個重要能力,ADB PG作爲一款功能強大、擴展性強的數據倉庫產品,基於PG 外表開發了多種數據源的分析和寫入能力,並且沉澱了很多性能優化技術。未來ADB PG將繼續在產品功能、性價比、雲原生能力、湖倉一體等方向繼續發力,爲用戶提供更多的功能、性能和成本優化。

原文鏈接

本文爲阿里雲原創內容,未經允許不得轉載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章