提升50%!Presto如何提升Hudi表查詢性能?

  • 2021 年 5 月 16 日
  • 筆記

分享一篇關於使用Hudi Clustering來優化Presto查詢性能的talk

talk主要分為如下幾個部分

  • 演講者背景介紹
  • Apache Hudi介紹
  • 數據湖演進和用例說明
  • Hudi Clustering介紹
  • Clustering性能和使用
  • 未來工作

該talk的演講者為Nishith Agarwal和Satish Kotha,其中Nishith Agarwal是Apache Hudi PMC成員,在Uber任職團隊Leader,Satish Kotha是Apache Hudi Committer,也在Uber任職軟體工程師。

什麼是Apache Hudi?Hudi是一個數據湖平台,提供了一些核心功能,來構建和管理數據湖,其提供的核心能力是基於DFS攝取和管理超大規模數據集,包括:增量資料庫攝取、日誌去重、存儲管理、事務寫、更快的ETL數據管道、數據合規性約束/數據刪除、唯一鍵約束、處理延遲到達數據等等。

現在Hudi在Uber內部的生產應用規模已經達到了一個新台階,數據總規模超過了250PB8000+張表,每天攝取5000億條數據。

基於Hudi的數據湖架構演進如下。通過批、流方式將數據以Hudi格式寫入數據湖中,而Hudi提供的事務、主鍵索引以及二級索引等能力均可加速數據的寫入,數據寫入Hudi後,數據文件的組織會以列存(基礎文件)和行存(增量日誌文件)方式存儲,同時藉助Hudi提供的各種表服務,如

  • Cleaning:清理服務,用來清理過期版本的文件;
  • Clustering:數據聚簇,將文件按照某些列進行聚簇,以重新布局,達到優化查詢性能的效果;
  • Replication:複製服務,將數據跨地域進行複製;
  • Archiving:歸檔服務,歸檔commit元數據,避免元數據不斷膨脹;
  • Compaction:壓縮服務,將基礎文件和增量日誌文件進行合併,生成新版本列存文件,提升查詢性能;

而對於查詢引擎而言,Hudi可以將其表資訊註冊至Metastore中,查詢引擎如Presto即可與Metastore交互獲取表的元資訊並查詢表數據。

由於Uber內部大規模使用了Presto查詢引擎,下面重點介紹Hudi和PrestoDB的集成細節。

現階段PrestoDB支援查詢兩種Hudi表類型:針對讀友好的COPY_ON_WRITE類型(存列存格式)和寫友好的MERGE_ON_READ類型(列存+行存格式);支援已經相對完備。

介紹完Hudi和PrestoDB集成現狀後,來看看使用案例和場景,Hudi與Presto的集成是如何降低成本和提高查詢性能的

大數據場景下,對於寫入(攝取)和查詢引擎的優化思路通常不同,可以從兩個維度進行對比,如數據位置和文件大小,對於寫入而言,數據位置一般決定於數據到達時間,文件大小則更傾向於小文件(小文件可減小寫入延遲);而對於查詢而言,數據位置會更傾向於查詢的數據在同一位置,文件大小則更傾向於大文件,小文件帶來額外的開銷。

有沒有一種方式可以兼顧寫入和查詢呢,答案是肯定的,引入Clustering,對於Clustering,說明如下。

  • Clustering是Hudi提供的一種改變數據布局的框架

    • 提供了可插拔的策略來重組數據;
    • 開源版本提供了一些開箱即用的策略;
  • Clustering還提供了非常靈活的配置

    • 可以單獨挑出部分分區進行數據重組;
    • 不同分區可使用不同方式處理;
    • 支援不同粒度的數據重組:全局、本地、自定義方式;
  • Clustering提供了快照隔離和時間旅行

    • 與Hudi的Rollback和Restore兼容;
    • 更新Hudi元數據和索引;
  • Clustering還支援多版本並發控制

    • Clustering可與攝取並發執行;
    • Clustering和其他Hudi表服務如Compaction可並發執行;

下面來看一個使用Clustering來提高查詢性能的案例,使用的的SQL如下select b,c from t where a < 10000 and b <= 50000;列舉了三種情況。

  1. 未下推但未進行Clustering,掃描的文件數很多;
  2. 下推但未進行Clustering,掃描及處理的文件數也很多;
  3. 下推並且進行Clustering,掃描及處理的數據量變得較少;

接著看看未進行Clustering之前的查詢計劃,總共掃描輸入了2900W+條數據,最後過濾輸出了140W+條數據,過濾掉數據的比例達95.17%;

經過Clustering之後的執行計劃,總共掃描輸入了371W+條數據,最後過濾輸出了140W+條數據;相比未進行Clustering,掃描的數據量從2900W+減少到了371W+;可見Clustering的效果提升非常顯著。

對於Clustering帶來的查詢性能優化如下

  • 未進行Clustering,掃描輸入數據量大小為2290MB,條數為2900W+,CPU耗時27.56S
  • 進行Clustering後,掃描輸入數據量大小為182MB,條數為300W+,CPU耗時6.93S

掃描數據量減少了10倍,CPU消耗減少了4倍,查詢延遲降低了50%+

基於Clustering可提供強大的的性能優化,在Uber內部也已經在生產上使用了Clustering,利用了Clustering可以和攝入並發執行的特性。生產中使用了兩條Pipeline,一條攝入Pipeline,一條Clustering Pipeline,這樣攝入Pipeline可以不斷產生新的小文件,而通過非同步的Clustering Pipeline將小文件合併,從而對查詢端暴露大文件,避免查詢端受寫入端產生太多小文件問題影響。

關於通過Clustering加速Presto的查詢性能上面已經講述完了,當然對於Clustering還有後續的規劃:落地更多的用例;將Clustering作為一個更輕量級的服務調用;分優先順序及分層(如多個Job跨表重組數據布局);根據歷史查詢性能優化新的數據布局;在Presto中添加二級索引進一步減少查詢時間;提升重寫性能(如對於某些策略降低重寫數據開銷);

好了,今天的分享就這裡,歡迎關注Hudi郵件列表[email protected] 以及 star & fork //github.com/apache/hudi