跳至主要內容
論文精煉 · Lakehouse

Lakehouse: A New Generation of Open Platforms that Unify Data Warehousing and Advanced Analytics(Lakehouse:統一資料倉儲與進階分析的新一代開放平台)

一份設計藍圖:直接在雲端物件儲存的開放 Parquet 檔案之上,做出倉儲級的交易、索引與 SQL 效能。

作者Michael Armbrust、Ali Ghodsi、Reynold Xin、Matei Zaharia(Databricks;UC Berkeley;Stanford University) 發表於CIDR 2021(第 11 屆 Innovative Data Systems Research 會議),線上舉行,2021 年 1 月 年份2016–2020,2020 年代成為主流
閱讀原始論文 PDF 所有論文

一口氣講完 — 整篇論文的濃縮

到 2021 年,幾乎所有大型企業都跑著兩層式架構:原始資料先 ETL 進由 Parquet 或 ORC 檔案構成的雲端 data lake,再把整理過的子集 ELT 進 Redshift、Snowflake 這類專有格式的資料倉儲。作者主張第二份副本純屬偶發性複雜度,換來的是可靠性問題、落後好幾天的資料、雙倍儲存成本、廠商鎖定,以及一個機器學習根本讀不動的架構。他們提出的 Lakehouse 只保留一份資料,放在廉價物件儲存上的開放、可直接存取的檔案裡,再在其上補齊倉儲功能:像 Delta Lake 這樣的交易式中繼資料層,用來界定哪些物件屬於某個資料表版本,加上快取、輔助統計與索引、以及資料佈局最佳化,在完全不改動檔案格式的前提下把 SQL 效能救回來。ML 與資料科學則透過宣告式 DataFrame API 存取同一批資料表,其延遲求值產生的查詢計畫會被推進同一套最佳化裡。在 scale factor 30,000 的 TPC-DS 上,Databricks Delta Engine 跑完全部 99 個查詢花 3302 秒、費用 104 美元,四套雲端資料倉儲則是 2996 到 37283 秒、153 到 570 美元。

在這篇論文之前 — 它所降落的世界

第一代分析平台把營運資料直接 ETL 進 schema-on-write 的資料倉儲;這套做法能撐住,直到 on-premises 一體機把運算與儲存綁在一起,逼企業照尖峰負載採購,也直到資料開始變成非結構化的影片、音訊與文件——那是 SQL 倉儲根本無法儲存與查詢的東西。第二代的答案是 data lake:從 Hadoop 與 HDFS 開始,用 schema-on-read 把所有原始資料便宜地丟進 Parquet、ORC 這類通用開放格式,資料品質與治理則往下游推。2015 年起,S3、ADLS、GCS 等雲端物件儲存以超過十個 9 的耐久性、跨地域複寫與封存層取代了 HDFS,但整體形狀沒變:一小塊整理過的子集仍要再 ETL 進 Teradata、Redshift 或 Snowflake,供真正重要的 BI 使用。作者指出,這種 data lake 加資料倉儲的兩層式模式,在他們的經驗裡幾乎所有 Fortune 500 企業都在用。其實產業的兩邊早已互相靠攏:主流資料倉儲都加上了對 Parquet 與 ORC 的 external table 支援,Spark SQL、Presto、Hive 與 Athena 也能直接查 data lake;但 external table 連接器往往很慢,因為引擎是為自家內部格式調校的,而 data lake 上的引擎又仍然缺少 ACID 交易與索引。

問題 — 當時真正壞掉的地方

  • 要讓 data lake 與下游資料倉儲保持一致,得投入持續不斷的 ETL 工程,而每多一個步驟就多一次失敗或程式錯誤的機會,悄悄地讓資料品質變差。
  • 兩套系統支援的資料型別、SQL 方言甚至資料表 schema 都不同,於是 lake 與倉儲之間的語意落差,成了錯誤資料的長期來源。
  • 倉儲裡的資料是舊的:新進資料要先落在獨立的暫存區,再靠週期性作業載入,常常一等就是好幾天;相對地第一代平台在載入當下就能查到營運資料。
  • TensorFlow、PyTorch、XGBoost 這些主流機器學習系統需要用複雜的非 SQL 程式碼吃進大量資料,走 ODBC 或 JDBC 效率極差,而倉儲的專有內部格式又完全無法直接存取。
  • 倉儲廠商對 ML 工作負載的建議是先匯出成檔案,等於再多加一段 ETL 與更多資料落後;改成直接在原始 data lake 上跑 ML,則要放棄 ACID 交易、資料版本與索引。
  • 總持有成本被兩件事推高:持續 ETL 與第二份儲存副本的費用,以及專有格式造成的鎖定,讓資料或工作負載搬到別的引擎變得昂貴。

核心概念 — 主要貢獻,以及它們為何成立

Lakehouse 的定義

論文把 Lakehouse 定義為:建構在低成本、可直接存取的儲存之上,同時提供傳統分析型 DBMS 管理與效能功能的資料管理系統,包括 ACID 交易、資料版本、稽核、索引、快取與查詢最佳化。它等於把兩層式架構的兩半合起來——來自 data lake 的廉價開放儲存(任何引擎都讀得到),加上來自倉儲的管理與最佳化機制。作者也直說這個結合的代價:允許直接存取,就等於放棄一部分關聯式 DBMS 奉為基石的資料獨立性,因為磁碟上的格式從此變成公開 API。他們押的注是:當初讓倉儲值得多存一份資料的那些功能,可以在開放格式之上重做,而不必關在封閉格式裡。

開放檔案之上的交易式中繼資料層

第一個關鍵想法是:大量資料仍以 Parquet 這類標準格式放在物件儲存,但在其上加一層交易式中繼資料層,界定哪些物件屬於資料表的哪個版本。既然資料表的成員關係變成一個以交易方式更新的集合,而不是目錄裡剛好存在的那些檔案,原子性、版本、time travel 與零複製 clone 就都能在中繼資料層實作,而客戶端仍然直接讀原本的 Parquet。這正是 Delta Lake、Apache Iceberg 與 Apache Hudi 已經出貨的設計。最關鍵的是這層抽象是加法式的:既有的 Parquet 目錄只要補上一份日誌,其第一筆記錄指向所有既存檔案,就成了受管理的資料表。

與格式無關的 SQL 效能手段

資料倉儲的速度來自儲存格式與執行引擎的共同設計,而 Lakehouse 做不到,因為格式是固定且公開的。論文的答案是:有三類最佳化完全不動資料檔案,因此可以套用在任何現在或未來的格式上——把熱資料以轉碼後的形式快取在 SSD 與記憶體、維護每個檔案的統計值與 Bloom filter 索引之類的輔助資料、以及透過叢集化記錄來最佳化資料佈局。之所以夠用,理由是冷熱分離:熱資料可以用封閉式倉儲會用的同一套結構快取起來,而放在物件儲存上的冷資料,效能主要由讀取量決定,佈局最佳化加上 zone map 正好能像專有引擎那樣把讀取量壓到最低。

以宣告式 DataFrame API 作為 ML 介面

ML 函式庫是用無法翻成 SQL 的命令式程式碼寫的,卻需要大量讀取資料,因此最直白的整合方式就是向中繼資料層問出資料表目前由哪些 Parquet 檔案組成,再交給函式庫。論文主張再往前一步:讓 DataFrame API 變成宣告式的,把轉換操作延遲求值,於是客戶端函式庫捕捉到的是一份關聯運算子計畫,而不是立刻執行。這份計畫可以被最佳化並下推到儲存層,讓 ML 的資料準備階段也享有和 SQL 相同的快取、資料跳過與佈局紅利。由於 DataFrame 是 Spark 分析生態系共通的資料型別,只要最佳化這一條路徑,MLlib、GraphFrames、SparkR 與眾多社群函式庫就一起加速。

把資料品質與治理放進中繼資料層

一旦有一層負責仲裁資料表存取,它就是強制正確性與政策最自然的位置,而不必信任每一個寫入端。Delta Lake 實作了 schema enforcement,要求上傳資料必須符合資料表 schema,另有 constraints API 讓資料表擁有者限制可寫入的值,客戶端函式庫會自動拒絕違規記錄或把它們隔離到特定位置。同一層也能當治理的收束點:在把讀取雲端物件儲存原始檔案的憑證交出去之前,先檢查客戶端是否有權存取該資料表,並可靠地記錄每一次存取。這正面打擊了 data lake 淪為 data swamp 的老問題——品質與治理被推到下游,然後永遠沒人解決。

開放格式作為治理與去鎖定的論證

除了效能與成本,論文還提出一套法規與組織面的理由來支持可直接存取的開放格式。日益嚴格的資料管理要求,意味著組織可能得在很短時間內搜尋舊資料集、刪除特定資料或更換處理基礎設施,而統一在開放格式上,等於保證這些事都不必卡在廠商身上。同樣的性質也讓 Lakehouse 很適合 data mesh 這類分散式團隊結構:每個資料集都能從物件儲存直接取用,消費端不必被安置到生產端的運算資源上。作者判讀軟體產業的長期方向就是走向開放資料格式,並預期企業資料會跟上。

被否決的替代路線

論文檢視並駁回了兩條通往相同目標的路。第一條是乾脆廢掉 data lake,把所有資料放進運算與儲存已分離的資料倉儲;作者稱之為 straw man,而它遲遲沒有被採用本身就是證據——它仍然難以處理影片、音訊與文字,也仍然不給 ML 快速的直接存取。第二條是在倉儲前面架一層大規模平行的服務層,像 Hive LLAP 那樣;作者判斷它營運更貴、更難管理,效能大概還不如直接存取物件儲存,而且會同時劣化物件儲存最吸引人的三個性質:低成本、對彈性工作負載的高頻寬、以及極高的可用性,最後還只是把「該選什麼高效讀取格式」的問題換個地方擺著。

運作方式 — 具體的機制

資料表狀態就是物件儲存裡的一份交易日誌

Databricks 從 2016 年開始開發的 Delta Lake,把「哪些物件屬於這個資料表」記成一份以 Parquet 格式存放在同一個 data lake 裡的交易日誌,因此不必額外跑一套服務就能擴展到每張表數十億個物件。源自 Netflix 的 Apache Iceberg 採用類似設計,同時支援 Parquet 與 ORC;源自 Uber 的 Apache Hudi 聚焦於簡化串流擷取,但不支援並行寫入者。這條血脈的源頭是 Apache Hive ACID,它用一套 OLTP DBMS 追蹤某個資料表版本包含哪些檔案,並讓對這個集合的更新具備交易性。導入成本很低,因為轉換只動中繼資料:寫入一份第一筆記錄就指向所有既存檔案的日誌,一個 Parquet 目錄就零複製地變成 Delta 資料表。

因為有交易,快取才安全

有了交易式中繼資料層,Lakehouse 就可以把物件儲存上的檔案快取到處理節點較快的裝置上,也就是 SSD 與記憶體,因為執行中的交易能從日誌判斷某個被快取的檔案對它的快照是否仍然有效。這消除了在可變檔案目錄上做快取最典型的失效風險。而且快取不必原樣保存位元組:它可以存成更適合執行引擎的轉碼表示,等同於封閉式倉儲在內部所做的最佳化。Databricks 的實作會把載入快取的 Parquet 資料部分解壓縮,用空間換取查詢時的解碼成本。

在基礎檔案旁維護輔助資料結構

基礎資料表格式必須保持可被直接 I/O 讀取,但系統對自己額外維護的檔案握有完全控制權。在 Delta Lake 與 Delta Engine 中,每個資料檔案的欄位 min 與 max 統計值就存放在儲存交易日誌的同一批 Parquet 檔案裡,查詢可以據此跳過那些值域根本不可能符合述詞的整個資料檔案。這種資料跳過的效益,取決於基礎資料在被過濾欄位上叢集得多好,這也是它必須和佈局最佳化搭配的原因。當時還在實作 Bloom filter 型的索引,作者並指出,沿著「對原始資料檔案建索引」那條研究線的各種結構,都可以放在同一個位置。

在固定格式內做資料佈局最佳化

即使格式凍結,系統仍然能決定記錄如何分布到各個檔案。最重要的槓桿是記錄排序,也就是決定哪些記錄被叢集在一起、因此可以一起便宜地讀出。Delta Lake 支援依單一維度排序,也支援 Z-order 與 Hilbert 這類空間填充曲線,藉此一次取得多個維度上的局部性,而不是只有排序鍵的第一個欄位。論文還勾勒了未來格式可以開放的其他佈局自由度,例如在每個資料檔案內以不同順序擺放欄位,或對不同的記錄群組採用不同的壓縮策略。

三種最佳化如何互相搭配

這些技術是針對分析型工作負載的傾斜存取模式設計的:大多數查詢集中打在一小塊熱資料上。這塊熱資料由快取以倉儲級的結構提供,因此它的效能完全不必受制於開放格式。冷資料仍留在物件儲存上,那裡的主要成本就是每個查詢讀了多少資料。此時用佈局把會被一起存取的記錄叢集起來,再用 zone map 決定要碰哪些檔案的哪些位元組範圍,就能讓引擎像專有的封閉式倉儲一樣把 I/O 壓到最低——即使它讀的是標準開放檔案。

宣告式 DataFrame 的執行路徑

在論文的示意流程中,使用者寫的是普通的 DataFrame 程式:載入 users 資料表、過濾出 buyer、投影出幾個欄位、把 null 補成 0,然後把結果交給模型的 fit 呼叫。這些都不會立即執行:Spark 的延遲求值把整段資料載入運算捕捉成一份查詢計畫,交給 Delta Lake 的客戶端函式庫。查詢規劃器會把選擇與投影下推進每一次讀取所對應的 data source plugin 類別,於是 Delta Lake 的 data source 可以套用快取、資料跳過與感知佈局的讀取,而不是先全掃再過濾。同時它也會查詢中繼資料層,決定目前這個資料表版本包含哪些分割與檔案。

存取控制與 ML 生命週期整合

由於客戶端最終是直接讀取雲端儲存上的原始物件,中繼資料層就成了施加政策的位置:它先驗證客戶端對該資料表的權限,才發出能讀取其檔案的憑證,並把這次存取寫進稽核日誌。在寫入端,schema enforcement 與 constraints API 會拒絕或隔離違反宣告 schema 或值域限制的記錄。對資料科學而言,Delta Lake 與 MLflow 的實驗追蹤服務整合,讓資料科學家能記錄某次實驗用的是哪個資料表版本,日後精確重建同一份資料——這正是臨時拼湊的檔案式管線給不了的可重現性。

論文證明了什麼 — 量測數據與證明

  • 在 scale factor 30,000 的 TPC-DS power test 上,使用 AWS、Azure 與 Google Cloud 上各 960 vCPU、搭配本機 SSD 的對等叢集,跑完全部 99 個查詢,四套匿名雲端資料倉儲分別耗時 2996 秒、7143 秒、5793 秒與 37283 秒,Delta Engine 在 on-demand 執行個體上為 3302 秒、在 spot 執行個體上為 3252 秒。
  • 同一組 power test 依各服務自身計價模式換算的費用,四套倉儲分別是 153、286、206 與 570 美元,Delta Engine 在 on-demand 上是 104 美元、在 spot 上是 56 美元。
  • 由於部分受測倉儲只支援節點附掛儲存,所有系統都在資料已快取於 SSD 的狀態下起跑;不過 Delta Engine 在冷快取起跑時也只慢了 18%,這替「它的成績有多少來自暖的本機儲存」設下了上界。
  • 論文指出這類中繼資料層方案的效能通常與原始 Parquet 或 ORC data lake 相當甚至更好,同時又多了交易、零複製 clone,以及回到資料表過去版本的 time travel。
  • Delta Lake 已被數千家客戶使用,約占 Databricks 一半的工作負載;自 2016 年起算,三年內成長到涵蓋平台上一半的運算時數——作者以此作為中繼資料層設計在規模上可行的證據。
  • 資料落後的說法引用了 Dimensional Research 與 Fivetran 的調查:86% 的分析師使用的是過時資料,62% 表示每個月都要多次等待工程資源。

限制與取捨 — 論文自承的,以及後來被發現的

  • 論文自承:Lakehouse 放棄了傳統 DBMS 相當大一部分的資料獨立性,因為儲存格式變成公開 API 的一部分,引擎因此永遠無法像封閉式倉儲那樣共同最佳化格式與執行。
  • 論文自承:把交易日誌放在同一個物件儲存簡化了維運、也帶來高讀取頻寬,但物件儲存的高延遲限制了每秒可支援的交易數,作者建議某些場景改用更快的中繼資料儲存會更好。
  • 論文自承:Delta Lake、Iceberg 與 Hudi 都只支援單一資料表的交易,跨資料表交易仍屬未來工作,而 Hudi 另外還不支援並行寫入者。
  • 論文有提到、但值得再強調:這組實驗並非全面勝出——有一套倉儲以 2996 秒完成 power test,快過 Delta Engine 的 3302 秒,所以真正的主張是「效能相當、成本更低」,而非全面更快;作者自己也說還有很大的最佳化空間。
  • 後續檢視才浮現:證據全部來自單一廠商,競品被匿名成 DW1 到 DW4,測試也由作者團隊自行執行;而 ML 那條線預設了以 Spark 為中心的世界——像 TensorFlow 的 tf.data 這類 API 根本不把查詢語意下推到儲存層,它們在意的是把資料載入與 CPU 到 GPU 的傳輸重疊起來,而論文也承認這個問題尚未解決。

它後來變成什麼 — 繼承這個想法的系統

這篇論文為一個類別命名並使之正當化:短短幾年內,lakehouse 就成了「建構在物件儲存之上、以開放表格式為基礎的分析平台」的標準說法。它點名的三個中繼資料層後來都變成關鍵基礎設施:Delta Lake 與 Apache Iceberg 逐步收斂成互通標準,Snowflake、BigQuery、Trino、Athena、DuckDB 與 ClickHouse 都能讀;而在 Databricks 併購 Tabular、Snowflake 開放 Polaris 之後,Iceberg 的 catalog 更成了兵家必爭的控制點。文中的 Delta Engine 後來以 Photon 之名發表於 SIGMOD 2022,是一套為 lakehouse 系統打造的向量化 C++ 執行引擎;而 Databricks Unity Catalog、Microsoft Fabric OneLake 與 AWS S3 Tables,則把論文「治理放在中繼資料層」的主張直接做成產品。具體機制也一併流傳下來:用於資料跳過的檔案級 min/max 統計、用於佈局的 Z-order 與後來的 liquid clustering、以及依資料表版本做 time travel,如今都是每個表格式的標配。宣告式 DataFrame 的主張同樣被驗證:Koalas 被吸收成 Spark 上的 Pandas API,Polars 與 Ibis 也都把延遲計畫下推到儲存層。對論文自身預言最強的反證是:資料倉儲並沒有凋零,而是走向收斂——Snowflake、BigQuery 與 Redshift 全都加上了一級的 Iceberg 資料表,於是產業從兩個方向同時抵達了論文所描繪的「開放格式、單一副本」終點。

論文原文 — 逐字引用

“We define a Lakehouse as a data management system based on low-cost and directly-accessible storage that also provides traditional analytical DBMS management and performance features such as ACID transactions, data versioning, auditing, indexing, caching, and query optimization.”

§3 The Lakehouse Architecture

“Regardless of the exact design, however, the core challenge is that the data storage format becomes part of the system's public API to allow fast direct access, unlike in a traditional DBMS.”

§3.3 SQL Performance in a Lakehouse

“According to a survey by Dimensional Research and Fivetran, 86% of analysts use out-of-date data and 62% report waiting on engineering resources numerous times per month [47].”

§1 Introduction

術語 — 依本篇論文的用法

Lakehouse
建構在低成本、可直接存取之儲存上的資料管理系統,同時提供傳統分析型 DBMS 的管理與效能功能,例如 ACID 交易、資料版本、稽核、索引、快取與查詢最佳化。
兩層式架構(two-tier architecture)
論文所攻擊的主流模式:原始資料先 ETL 進 data lake,整理過的子集再 ELT 進另一套資料倉儲,結果是兩份副本、多出來的管線,以及隨之而來的可靠性與資料落後問題。
中繼資料層(metadata layer)
疊在物件儲存之上的交易層,記錄哪些物件屬於資料表的哪個版本,藉此在不改動底層檔案格式的前提下實作 ACID 交易、版本與 time travel。論文舉的例子是 Delta Lake、Apache Iceberg 與 Apache Hudi。
輔助資料(auxiliary data)
Lakehouse 在不可變的基礎資料旁自行維護、且完全掌控的額外檔案,例如每個檔案的欄位 min/max 統計或 Bloom filter 索引,用來加速查詢而不必碰開放儲存格式。
資料跳過(data skipping)
利用每個檔案的統計值(也稱 zone map)判定某個資料檔案不可能包含符合述詞的任何列,因而整個略過不讀。其效果取決於基礎資料在被過濾欄位上叢集得多好。
Z-order 排序
一種資料佈局技術,沿著空間填充曲線(Z-order 或 Hilbert 曲線)排列記錄,讓在多個維度上都相近的記錄落在同一批檔案,取得單一排序鍵給不了的多維局部性。
宣告式 DataFrame API
轉換操作採延遲求值的 DataFrame 介面:客戶端函式庫捕捉到的是一份關聯運算子計畫並交給最佳化器,而不是一步步立即執行,讓 ML 的資料準備也能享用 Lakehouse 的快取、統計與佈局最佳化。
零複製 clone 與 time travel
中繼資料層帶來的管理功能:建立一個引用既有檔案、卻不複製任何資料的新邏輯資料表;以及讀取較早日誌記錄所記載的物件集合,查詢資料表的過去版本。
資料獨立性(data independence)
關聯式系統的原則:客戶端只看到邏輯 schema,實體表示由系統掌控。Lakehouse 刻意放棄其中一部分,因為儲存格式變成外部讀取端所依賴的公開 API。

在時間軸上的位置 — 這篇論文在整段故事中的座標

在時間軸上查看