S3 分割 (partitioning) 與檔案格式選擇是資料工程師在 AWS 資料湖中能做的兩個最具影響力的決策。在 DEA-C01 考試中,它們出現在網域 2、3 和 4 中,場景涉及 Athena 查詢成本、Glue ETL 處理量、Redshift Spectrum 掃描大小以及串流擷取下的結構描述演進 (schema evolution)。來自 Tutorials Dojo、ExamCert.App 以及 AWS in Plain English 等社群學習指南都指出了同樣的難點:考生對小型資料集過度分割並造成「分割爆炸」反模式,選擇 CSV 格式 (僅因熟悉) 卻在每次 Athena 查詢時支付比 Parquet 高出十倍的費用,且在分割投影 (partition projection) 本可免費使用時仍對擁有數千個分割的資料表執行 MSCK REPAIR TABLE。在考試中選錯就意味著在生產環境中選錯:選擇一個高基數 (high-cardinality) 的分割鍵 (如使用者 ID),單次 Athena 查詢在讀取任何資料前就需掃描數百萬個分割中繼資料分錄;為十億列的分析事實資料表選擇以列為導向的 Avro 格式,Athena 即使只選取兩欄也會讀取每一欄。
本指南是從資料工程師的角度編寫的。內容涵蓋什麼是分割及其重要性、支援 Athena 與 Glue 的 Hive 樣式分割佈局、分割基數的權衡、三種單欄式格式 Parquet 與 ORC 以及以列為基礎的 Avro、每種格式的首選時機、具備 ACID 與時間旅行功能的 Apache Iceberg 開放式資料表格式、EMR 上的 Apache Hudi 與 Delta Lake、作為 MSCK REPAIR TABLE 替代方案的分割投影、小檔案問題與合併 (compaction) 策略,以及典型的考試陷阱。最後,分割與格式的決策應該會像在關聯式資料庫資料表上選擇索引一樣自然。
為什麼 S3 資料湖的分割如此重要
分割是指組織物件儲存空間的實踐,以便查詢引擎可以跳過不需要讀取的資料。如果沒有分割,Athena 必須掃描資料表前綴中的每個檔案的每個位元組才能回答查詢,即使查詢帶有嚴格的述詞 (如「where year equals 2024 and month equals 04」)。透過分割,Athena 僅讀取相關的前綴並完全跳過其餘部分。
查詢成本與效能
Athena 每掃描 1 TB 資料收費 5 美元。一個擁有 5 TB 資料且未經分割的原始資料表,執行一次查詢需支付 25 美元,即使該查詢僅需一天的資料。若按天分割,同樣的查詢僅讀取 365 個分割中的一個,成本約為 7 美分。這 365 倍的節省效果,使分割成為資料湖中影響最大的單一優化手段。
資料在地性與平行處理
除了節省成本,分割還能讓查詢引擎平行處理。擁有一百個執行程式 (executors) 的 EMR Spark 可以同時讀取一百個分割,每個執行程式從其指派的前綴中擷取檔案。分割也是增量處理的自然單位 — Glue 作業書籤與 Iceberg 快照語義均在分割或檔案粒度上運作。
生命週期管理
分割為生命週期與保留期提供了自然邊界。按天分割的資料表可以擁有一個刪除超過九十天分割的 Glue 作業、一個將特定日期前綴轉換為 Glacier 的 S3 生命週期策略,或一個移除過期版本的 Iceberg expire-snapshots 作業。如果沒有分割,所有這些作業都需要逐個物件進行掃描與標記。
白話文解釋 S3 Partitioning And File Formats
分割與格式的決策樹很難僅憑名稱來直觀理解。三個具體的比喻能讓這些權衡變得好記。
比喻 1 — 圖書館卡片目錄與書架佈局
想像一個擁有五十萬本書的研究圖書館。圖書管理員設計了這棟建築,書籍按學科、作者、年份依次擺放。一位讀者詢問「是否有 2024 年出版的關於雲端運算的書籍」,他直接走向電腦科學走道,找到雲端運算子部分,並取出 2024 年的書架 — 圖書館跳過了五十萬本中不屬於雲端運算或不是 2024 年出版的書。這種擺放方式就是分割 (partitioning) — 讓搜尋跳過無關材料的物理組織。
現在想像書籍本身。每本書前面都有目錄,後面都有索引。讀者搜尋「EC2 執行個體類型」時直接翻到索引,找到頁碼引用,並僅閱讀這些頁面 — 他們不需要閱讀全書的每個字。那個索引就是單欄式儲存 (column-oriented storage) — 讓查詢僅讀取所需欄位的檔案內物理組織。Parquet 與 ORC 就像每本書都有索引和章節結構的圖書館;CSV 與 JSON 則像沒有索引的書,讀者必須按順序翻閱每一頁。
比喻 2 — 倉庫走道系統
想像一個 Amazon 履行中心。物品按類別、SKU、批次日期儲存。當收到一份訂單,要求「2024 年 4 月批次的 10 號藍色慢跑鞋」時,揀貨員走向「鞋類」,然後走向「運動類」,最後走向「2024 年 4 月」那一行。走道標誌 (分割鍵) 告知揀貨員應跳過哪些走道。如果物品是按到達順序且沒有走道結構地存放,揀貨員在處理每份訂單時都必須走遍每個走道 — 這正是 Athena 在未分割的資料表上所做的事。
但這裡有一個權衡。如果倉庫按 SKU 加上批次日期再加上序號進行分割,每個單獨的物品都會擁有自己的儲位 — 數十億個儲位,大多數時間都是半空的,揀貨員花在閱讀儲位標籤上的時間比揀貨時間還多。這就是分割爆炸 (partition explosion) — 分割過多且基數過低。正確的分割應與預期的查詢模式匹配:針對查詢經常過濾的欄位進行分割,並保持分割大小具備意義 (經驗法則為每個分割數 GB 到數十 GB)。
比喻 3 — 報紙檔案館
想像一個縮影膠片上的報紙檔案館。每年都有自己的捲軸;在捲軸內,文章按日期、版面、頁碼組織。一位歷史學家搜尋「2003 年的所有體育文章」,他載入 2003 年的捲軸並捲動到體育版 — 他不需要載入 2002 年或 2004 年的捲軸,且在 2003 年內不需要捲動新聞版。每年一個捲軸的結構就是分割佈局;捲軸上的版面結構就是每個檔案內的單欄式佈局。
現在想像報紙發布了更正啟事。對於 Parquet 不可變檔案,更正意味著重寫整個受影響的檔案 — 很笨拙。對於 Apache Iceberg,更正是一次交易更新,它會寫入一個新檔案以及指向新版本資料表快照的中繼資料,而舊的讀者仍可透過「時間旅行」讀取先前的快照。Iceberg 增加了一個等同於「2026 年 4 月 30 日的檔案館是什麼樣子」的查詢,這是在不保留多份完整副本的情況下縮影膠片無法做到的。這就是從「S3 上的 Parquet」到「託管資料表格式」的飛躍。
Hive 樣式分割佈局
AWS 的標準分割佈局是 Hive 慣例。
年-月-日模式
Hive 樣式分割使用 key=value 的前綴區段。一個按天分割的事件資料表看起來像 s3://bucket/events/year=2024/month=04/day=15/file.parquet。Athena、Glue Data Catalog 與 Spark 都會自動識別這種慣例 — 前綴中的金鑰部分會成為資料表結構描述中的分割欄位,且帶有 WHERE year=2024 AND month=04 的查詢會將述詞下推到前綴掃描並跳過所有其他分割。
分割鍵選擇
正確的分割鍵是大多數查詢會進行過濾的欄位 — 通常是時間序列工作負載的日期或時間戳記組件。國家、地區、客戶 ID 或產品類別也可以作為分割鍵,但前提是基數受限且查詢確實會過濾它們。錯誤的分割鍵是使用者 ID、交易 ID 等高基數欄位,或任何擁有超過一萬個相異值的欄位 — 針對這些欄位進行分割會造成分割爆炸。
分割基數權衡
經驗法則是:目標分割大小應在 GB 到數十 GB 範圍內。較小的分割會增加中繼資料開銷與小檔案問題;較大的分割則會降低平行度並阻礙 Athena 跳過無關資料。對於每天 1 TB 的典型事件串流,每天一個分割 (1 TB) 是可行的;對於每天 1 GB 的串流,每週或每月一個分割會更好。考試常設局過度分割的場景 — 「按使用者 ID 分割」幾乎總是錯誤的。
多層級分割
年、月、日是最常見的多層級佈局。對於極高容量的串流 (數兆個事件),增加「小時」作為第四層級是可行的,但如果單個小時僅產生微小檔案,則會引入小檔案問題。將日期與另一個維度 (如 年/月/日/地區) 混合也是可以的,前提是地區基數受限 (少於五十個值)。
分割 (partition) 是 S3 前綴的子目錄,其名稱編碼了欄位值,允許查詢引擎僅讀取與查詢濾述詞匹配的分割。 Hive 慣例 key=value/key=value/... 是 AWS 分析服務自動識別的標準佈局。分割不是資料 — 它們是給查詢規劃器的裁剪指令。針對查詢不會過濾的欄位對資料表進行分割不但毫無價值,還會增加中繼資料開銷。針對高基數 (數千或數百萬個相異值) 的欄位進行分割會造成分割爆炸,這減慢查詢規劃器的速度甚至超過了加速資料掃描帶來的好處。DEA-C01 考試透過場景測試這一點,要求考生為工作負載設計分割策略 — 正確答案應平衡預期的查詢模式與預期的分割大小。
Parquet — 預設的單欄式格式
Parquet 是 AWS 資料湖工作負載的預設檔案格式。
為什麼首選 Parquet
Parquet 按欄 (column) 而非按列 (row) 儲存資料。選取五十欄中兩欄的查詢僅讀取這兩欄的位元組 — 其他四十八欄在磁碟上被物理跳過。結合述詞下推 (檔案的列群組統計資訊讓讀取器能跳過值範圍不匹配述詞的列群組) 與欄位級壓縮 (每欄都使用最適合其類型的編解碼器進行壓縮),Parquet 在 Athena 上比 CSV 或 JSON 等列導向格式能降低十倍以上的成本。
Parquet 內部結構
一個 Parquet 檔案被劃分為多個列群組 (row groups,通常每個 128 MB)。在每個列群組內,資料按欄佈局,且每欄、每個列群組都有統計資訊 (最小值、最大值、null 計數)。檔案頁尾 (footer) 持有關於列群組與欄位的中繼資料。Athena 首先讀取頁尾,利用統計資訊對比述詞決定可以跳過哪些列群組,然後僅讀取查詢所需的欄位區塊。
壓縮編解碼器 (Compression Codecs)
Snappy 是預設值 — 速度快、壓縮率適中。GZIP 與 ZSTD 提供更高的壓縮率,但 CPU 成本較高。ZSTD 已成為新管道的最佳通用選擇 (壓縮率優於 GZIP,解壓縮速度也快於 GZIP)。根據儲存成本與查詢 CPU 成本來選擇編解碼器 — 通常 Snappy 即可,若儲存是瓶頸則選 ZSTD。
Parquet 與 Glue、Athena、EMR、Redshift Spectrum
當你使用 glueparquet 格式時,Glue ETL 預設寫入 Parquet。Athena 以原生方式查詢 Parquet,支援單欄剪裁與述詞下推。EMR Spark 使用 Spark SQL Parquet 讀取器讀取 Parquet。Redshift Spectrum 從運算節點平行掃描 S3 中的 Parquet。每個 AWS 分析服務都優先針對 Parquet 進行優化。
ORC — Hive 優化格式
ORC (Optimized Row Columnar) 是 AWS 支援的第二種單欄式格式。
何時 ORC 優於 Parquet
ORC 是專門為 Hive 設計的,在 Hive 工作負載上仍保持微弱優勢 — 壓縮更好、統計資訊更緊湊、原生支援 ACID 交易。寫入 ORC 的 EMR Hive 作業能看到優於 Parquet 的適度收益。EMR 上的新版 Hive 也能很好地運作於 Parquet,因此差距已縮小。
ORC 內部結構
ORC 檔案擁有帶狀區域 (stripes,相當於 Parquet 的列群組),每個帶狀區域都有欄位統計索引,檔案頁尾持有中繼資料。結構概念上與 Parquet 相似,但針對 Hive 的特定存取模式進行了優化。
ORC 與 AWS 服務
Glue ETL 支援 ORC 作為輸入與輸出。Athena 以原生方式讀取 ORC。Redshift Spectrum 支援 ORC。考試將 Parquet 視為預設值,將 ORC 視為 Hive 特定的替代方案 — 除非工作負載是由 Hive 驅動的,否則請選 Parquet。
Avro — 以列為基礎的串流格式
Avro 與 Parquet 和 ORC 根本上不同。
為什麼 Avro 是以列為基礎的
Avro 按列儲存資料,並在檔案標頭中嵌入結構描述。讀取任何一欄都需要讀取整列。寫入一列不需要隨機存取 — 將資料列附加到檔案末尾即可。這使 Avro 成為串流寫入的理想選擇,因為資料列是逐個到達的,寫入器無法高效地將其分批為單欄式佈局。
何時首選 Avro
Avro 是 Kafka 與 Kinesis 進行串流擷取的典型格式。生產者在資料到達時寫入列;取用者從檔案標頭讀取結構描述並解析列。Avro 與 Glue Schema Registry 自然搭配,後者為串流管道強制執行結構描述相容性 — Kafka 主題中的每條訊息都符合註冊的 Avro 結構描述,具備回溯、向前或完全相容性規則,以防止破壞性變更。
結構描述演進 (Schema Evolution)
Avro 的最大優勢是結構描述演進。新增一個帶有預設值的欄位是回溯相容 (backward compatible) 的 — 舊讀者可以讀取新資料,因為新欄位有預設值。移除一個選用欄位是向前相容 (forward compatible) 的 — 新讀者可以讀取舊資料。完全相容 (Full compatibility) 則需要兩者兼具。Schema Registry 在訊息發布時強制執行這些規則,防止生產者破壞取用者的運作。
Avro 對比 Parquet — 何時轉換
常見的管道模式:串流事件以 Avro 格式到達 Kinesis 或 Kafka,預備到 S3,然後由 Glue 或 Spark 作業將其轉換為 Parquet 以進行分析。Avro 是對寫入者友善的格式;Parquet 是對讀取者友善的格式。轉換通常在分割關閉時 (例如一天結束) 進行排程或觸發。
將分析資料表儲存為 CSV、JSON 或 Avro 而非 Parquet 或 ORC 會使 Athena 掃描成本增加十倍以上 — Athena 按掃描位元組收費,而以列為導向的格式迫使引擎即使查詢僅選取兩欄也必須讀取每一欄。 DEA-C01 考試透過場景測試這一點,描述分析儀表板在 Athena 上「過於昂貴」,並詢問成本最低的優化方案。錯誤答案通常是增加 Athena 工作群組限制或查詢結果快取;正確答案是將底層資料轉換為 Parquet (通常透過執行一次分割關閉後的 Glue 或 EMR 作業)。將 Parquet 轉換與分割相結合,成本降低可達兩到三個數量級。熟悉關聯式資料庫的工程師有時會抵制這一點,因為 CSV「更容易檢查」 — 這對於預備區 (staging) 是可以的,但對於生產分析則是錯誤的。
Apache Iceberg — S3 上的開放式資料表格式
Iceberg 是 AWS 已標準化的現代資料表格式。
Iceberg 在純 Parquet 之上增加了什麼
S3 上的純 Parquet 只是檔案佈局 — 沒有「資料表的當前狀態」的概念。Iceberg 在 Parquet (或 ORC 或 Avro) 之上增加了中繼資料層,追蹤哪些檔案是哪個資料表快照的一部分,從而實現 ACID 交易、結構描述演進、分割演進以及時間旅行查詢。Iceberg 之於 Parquet,就像 Git 之於資料夾中的純檔案 — 底層儲存相同,但語義強大得多。
Iceberg ACID 交易
Iceberg 中的插入、更新、刪除與合併都是原子性的 — 要麼作業完成且新快照變為當前狀態,要麼作業失敗且舊快照保持不變。並行寫入者透過對中繼資料檔案的樂觀並行控制 (optimistic concurrency control) 進行序列化。這解決了資料湖中常見的問題:讀取者在長時間執行的 ETL 作業期間看到部分寫入的資料。
結構描述與分割演進
Iceberg 讓你能新增、刪除或重新命名欄位而無需重寫歷史資料。更重要的是,它讓你能變更分割規格 (例如從按月變更為按天) 而無需重寫舊資料。舊資料保留舊的分割規格;新資料使用新規格;查詢則透明地處理兩者。純 Parquet 無法做到這一點。
時間旅行 (Time Travel)
每個 Iceberg 快照都會保留 (受過期快照策略限制)。查詢可以使用 SELECT ... FOR TIMESTAMP AS OF '2024-04-01' 並讀取該歷史時刻的資料表狀態。使用案例包括重現模型訓練資料集、稽核資料變更以及復原意外的異動。
AWS Glue、Athena、EMR、Redshift 中的 Iceberg
Glue Data Catalog 以原生方式支援 Iceberg 資料表。Athena 以完整的 ACID 語義讀寫 Iceberg。EMR Spark 與 EMR Serverless 支援 Iceberg。Redshift Spectrum 可以讀取 Iceberg 資料表。AWS 已將 Iceberg 列為首選的開放式資料表格式 — EMR 上仍支援 Hudi 與 Delta Lake,但對於新的湖倉一體 (lakehouse) 工作負載,Iceberg 是預設推薦。
EMR 上的 Apache Hudi 與 Delta Lake
EMR 上還會出現另外兩種開放式資料表格式。
Apache Hudi
Hudi (Hadoop Upserts Deletes and Incrementals) 是針對 CDC (變更資料擷取) 密集型工作負載設計的。兩種儲存模式:寫入時複製 (Copy on Write,每次更新都重寫檔案 — 讀取優化) 與讀取時合併 (Merge on Read,寫入增量,讀取時合併 — 寫入優化)。Hudi 在串流更新插入 (upsert) 管道中表現強勁,但營運複雜度高於 Iceberg。
Delta Lake
Delta Lake 是源自 Databricks 的資料表格式。EMR 支援它以相容於針對 Databricks 設計的 Spark 工作負載。在 ACID 語義、結構描述演進與時間旅行方面與 Iceberg 功能相似。
如何在 Iceberg、Hudi、Delta Lake 之間選擇
對於新的 AWS 工作負載,請選擇 Iceberg — 它是 AWS 推薦的格式,具備最佳的服務整合。僅對於極高頻率的串流更新插入工作負載才選擇 Hudi。僅在將現有的 Databricks Delta 資料表移植到 EMR 時才選擇 Delta Lake。
分割投影 — 消除 MSCK REPAIR TABLE
分割探索是資料湖中第二大的效能痛點。
MSCK REPAIR TABLE 問題
當新分割進入 S3 時,Athena 不會自動知道它們。經典的修正方法是 MSCK REPAIR TABLE table_name,它掃描 S3 前綴、探索分割目錄並將其新增至 Glue Data Catalog。問題:當資料表規模達到數萬個分割時,MSCK REPAIR TABLE 需要幾分鐘到幾小時,且每次執行都會消耗顯著的 Athena 掃描預算。
分割投影 (Partition Projection) 如何運作
分割投影告知 Athena 如何計算分割值,而無需諮詢目錄。你聲明投影規則 — 「年份是 2020 到 2030 的整數,月份是 1 到 12 的整數,日期是 1 到 31 的整數,格式是 year=$1$/month=$2$/day=$3$」 — Athena 在查詢時直接從述詞計算匹配的前綴列表。無需目錄查閱,無需 MSCK REPAIR TABLE。
何時使用分割投影
當分割值可以從規則中預測時使用投影 — 日期分割、整數範圍、列舉值。當分割稀疏或命名不規則時不要使用投影。投影是在 Athena 或 Glue 中建立資料表時,於資料表屬性中配置的。
投影對比編目程式 (Crawler)
Glue 編目程式也會探索分割,並排程定期執行。投影更快 (無需掃描) 且免費 (無編目程式 DPU 費用)。對按時間分割的分析資料表使用投影;對結構描述不可預測或分割探索較複雜的資料表使用編目程式。
分割投影透過在查詢時從聲明的規則計算分割值,消除了按時間分割資料表的 MSCK REPAIR TABLE 與 Glue 編目程式成本 — Athena 僅讀取與查詢述詞匹配的前綴,而無需在 Glue Data Catalog 中查閱分割中繼資料。 對於擁有數千或數萬個日期分割的資料表,投影將查詢規劃時間從數秒縮短至數毫秒,並移除了在每個新分割產生時執行 MSCK REPAIR TABLE 的營運負擔。在建立資料表時的 TBLPROPERTIES 中配置投影,聲明每個分割欄位的類型 (整數、列舉、日期、注入) 與範圍。DEA-C01 考試常將此作為「如何消除管道中的 MSCK REPAIR TABLE」場景 — 正確答案是分割投影,而非更頻繁的編目程式排程。
小檔案問題與合併 (Compaction)
小檔案是資料湖中沈默的效能殺手。
為什麼小檔案有害
Athena、Spark 與 EMR 都有每個檔案的開銷 — 開啟每個檔案都需要一次 S3 GET、一次中繼資料解析與讀取器初始化。讀取一萬個 1 MB 檔案的查詢比讀取一百個 100 MB 檔案的查詢慢得多,即使兩者包含相同的資料。經驗法則是:Parquet 資料表的目標檔案大小應在 128 MB 到 1 GB 之間。
為什麼會產生小檔案
按時間間隔 (每分鐘) 刷新的串流管道會產生許多小檔案。未將輸入檔案分組的 Glue ETL 作業會為每個輸入分割發出一個輸出。高平行度但每個工作資料量低的 Spark 作業會為每個工作發出一個檔案。
Glue groupFiles 選項
Glue 擁有 groupFiles="inPartition" 選項,在處理前自動將小輸入檔案分組為單一內存分割。對讀取許多小檔案 (典型如串流衍生的預備資料) 的 Glue 作業使用此選項。
合併 (Compaction) 策略
對於累積了小檔案的資料表,執行定期的合併作業,讀取一個分割中的所有檔案並將其重寫為一個或幾個大檔案。Iceberg 內建了 RewriteDataFiles 程序來執行此作業。Glue 與 EMR Spark 可以將合併作為排程作業執行。考試常將合併作為「Athena 效能隨時間下降」場景的補救策略。
分割與檔案格式的常見考試陷阱
DEA-C01 考試設定了一組一致的陷阱。請記住這六個。
陷阱 1 — 高基數分割鍵
場景描述按使用者 ID、交易 ID 或任何擁有數千或數萬個相異值的欄位進行分割。正確答案:按日期或其他低基數欄位分割;使用者 ID 可以作為檔案內的排序鍵,但不能作為分割鍵。
陷阱 2 — 對分析資料表使用 CSV
場景描述一個昂貴的 Athena 儀表板,其底層資料為 CSV。正確答案:透過 Glue 或 EMR 作業將其轉換為 Parquet 並重新執行儀表板。
陷阱 3 — 使用 Avro 進行 Athena 讀取
場景描述存放在 S3 上並由 Athena 查詢的 Avro 資料。正確答案:將 Avro 保留在 Kafka/Kinesis 擷取預備層,但將其轉換為 Parquet 供查詢層使用。Avro 是以列為基礎的,Athena 無法對其執行單欄剪裁。
陷阱 4 — 對大型資料表執行 MSCK REPAIR TABLE
場景描述每小時執行一次 MSCK REPAIR TABLE 並抱怨其成本。正確答案:配置分割投影或使用具備增量編目功能的 Glue 編目程式。
陷阱 5 — 需要 ACID 時使用純 Parquet
場景描述並行寫入者覆寫 S3 上的純 Parquet 並看到部分讀取。正確答案:遷移到 Iceberg (或 Hudi 或 Delta Lake) 以獲得交易語義。
陷阱 6 — 串流管道中的小檔案
場景描述一個串流衍生的資料表,其查詢速度在幾個月內變慢。正確答案:執行合併作業重寫小檔案為大檔案,理想情況下使用 Iceberg 的 RewriteDataFiles 或排程的 Glue 作業。
陷阱 7 — 未經下推的分割
場景描述按查詢不會過濾的欄位進行分割。正確答案:按查詢實際會過濾的欄位重新分割 — 除非查詢能將過濾器下推到分割層,否則分割是無效的。
對於 AWS 資料湖分析:Parquet 是讀取的首選單欄式格式,Avro 是串流寫入的首選列格式,ORC 是 Hive 特定的替代方案,而 Iceberg 是在 Parquet 檔案之上增加 ACID 語義的首選開放式資料表格式。 請記住:Athena 用 Parquet,Hive 用 ORC,Kafka/Kinesis 用 Avro。請記住:按日期欄位分割,而非按高基數 ID 分割。請記住:目標檔案大小 128 MB 到 1 GB,並在小檔案累積時進行合併。請記住:對於按時間分割的資料表,使用分割投影而非 MSCK REPAIR TABLE。這五條規則能回答 DEA-C01 考試中大部分的分割與格式場景。
關鍵數據與必須記住的格式事實
格式對比
- Parquet:單欄式導向、分析的預設值、述詞下推、單欄剪裁
- ORC:單欄式導向、Hive 優化、原生 ACID、在 Hive 上比 Parquet 略高效
- Avro:以列為導向、結構描述在檔案標頭、適用於帶有 Schema Registry 的串流
- CSV/JSON:以列為導向、無統計資訊、Athena 掃描成本比 Parquet 貴十倍
壓縮編解碼器
- Snappy:預設、速度快、壓縮適中
- GZIP:壓縮更高、速度較慢
- ZSTD:最佳通用、在兩方面均優於 GZIP
- LZO:舊式、在新管道中已棄用
分割規則
- Hive 慣例:
key=value/key=value/ - 目標分割大小:每個分割 1 GB 到 100 GB
- 避免對相異值超過 10,000 個的欄位進行分割
- 分割鍵必須是查詢會過濾的欄位
檔案大小目標
- Parquet 目標:每個檔案 128 MB 到 1 GB
- 較小檔案:增加中繼資料開銷與 Athena 掃描時間
- 較大檔案:降低平行度
Iceberg 能力
- S3 上的 ACID 交易
- 無需重寫即可演進結構描述
- 無需重寫即可演進分割
- 透過 FOR TIMESTAMP AS OF 進行時間旅行查詢
- Glue、Athena、EMR、Redshift Spectrum 原生支援
DEA-C01 考試重點 — S3 分割與檔案格式 Parquet、ORC、Avro。 此主題在 DEA-C01 考試中佔有相當權重。掌握每個 AWS 服務所暴露的權衡、決策邊界以及成本/效能觸發點 — 考試將測試那些依賴於知道哪個服務是錯誤答案,而不僅僅是哪個服務是正確答案的場景。
考試當天小貼士。 當 DEA-C01 場景幹同時提到成本、延遲或營運開銷限制時,在比較其餘選項的權衡前,先排除違反任何一項限制的選項。僅此一項過濾器就能解決很大一部分 DEA-C01 的多項正確選項場景。
常見問題 (FAQ) — S3 分割與檔案格式
Q1 — 我該如何為新的分析資料表在 Parquet 與 ORC 之間做選擇?
對於幾乎所有新的 AWS 工作負載,請選擇 Parquet。Parquet 在 AWS 服務 (Athena、Glue、EMR、Redshift Spectrum、QuickSight 均預設為 Parquet) 中整合更廣、工具更好,且具備與 ORC 相同的單欄剪裁與述詞下推優勢。僅當工作負載專門是 EMR 上的 Hive、大量使用 Hive ACID 交易且遷移成本很高時才選擇 ORC。考試將 Parquet 視為預設值;ORC 是舊式 Hive 商店的利基選擇。
Q2 — 我應該何時使用 Avro 而非 Parquet?
在串流擷取邊界使用 Avro。Kafka 生產者與 Kinesis 生產者將紀錄以 Avro 格式寫入,並在 Glue Schema Registry 中註冊結構描述,Registry 強制執行結構描述相容性,且 Avro 以列為導向、對附加友好的格式適合逐條記錄寫入。一旦資料進入 S3 並跨入分析層,請透過 Glue、EMR 或 Lambda 作業將其轉換為 Parquet — 因為 Avro 是以列為基礎的,Athena 無法對其執行單欄剪裁,因此針對 S3 上的 Avro 執行的查詢成本會比針對同一資料的 Parquet 高出十倍。
Q3 — 對於每日到達的事件串流,我應該使用什麼分割策略?
按日期組件分割:year=YYYY/month=MM/day=DD/。對於極高容量 (每天超過 1 TB) 的串流,可選擇性增加「小時」。避免按使用者 ID、交易 ID 或其他高基數欄位分割 — 這些應作為檔案內的排序鍵,而非分割鍵。對於可預測的日期分割,請配置 Athena 分割投影,這樣就永遠不需要執行 MSCK REPAIR TABLE,且查詢時無需在 Glue Data Catalog 中查閱分割中繼資料。目標分割大小應在 GB 範圍內 — 如果串流較小,請按月或按週分割,而非按天。
Q4 — 我該如何將純 Parquet 資料表遷移到 Apache Iceberg?
有兩條路徑。原位遷移 (In-place migration):使用 Athena 或 Spark 透過 ALTER TABLE ... CONVERT TO ICEBERG (或等效的 Spark 程序) 將現有的 Parquet 檔案註冊為初始 Iceberg 快照 — 速度快,但要求 Parquet 佈局必須與 Iceberg 相容。重寫遷移 (Rewrite migration):建立一個新的 Iceberg 資料表並透過 INSERT INTO new_table SELECT * FROM old_table 複製資料 — 較慢但更乾淨,且讓你能同時變更分割規格或結構描述。遷移後,下游查詢仍可繼續運作,因為 Iceberg 資料表暴露的 SQL 介面與 Hive 資料表相同。
Q5 — 我該如何防止串流管道中的小檔案問題?
有三個層面。第一,在寫入端配置緩衝 (buffering) — Kinesis Firehose 在寫入 S3 前可緩衝最多 128 MB 或 900 秒,以產生較大的檔案。第二,定期執行合併作業 (compaction job) — Iceberg 的 RewriteDataFiles 程序或自訂 Glue 作業會讀取一個分割中的許多小檔案並將其重寫為一個或幾個較大的檔案。第三,當讀取帶有許多小檔案的預備資料時,使用 Glue groupFiles="inPartition",這樣 Glue 作業會在處理前在內存中將輸入分組。考試模式為「串流衍生資料表上的查詢變慢」 — 答案是合併。
Q6 — 我應該何時使用分割投影對比 Glue 編目程式?
當分割值可以從規則中預測時 (如基於時間的分割、整數範圍、列舉值),使用分割投影。投影對每次查詢無額外成本,永遠不需要 MSCK REPAIR TABLE,並直接從資料表定義本身提供分割值。當分割值不可預測或資料表結構描述本身會發生變化時,使用 Glue 編目程式 — 編目程式會掃描 S3、推斷結構描述並更新 Data Catalog。對於帶有日期分割的典型分析資料表,投影是正確答案;對於結構化程度較低的探索性資料,編目程式是適當的。
Q7 — 對於一個十億列的每日事實資料表,正確的分割數量是多少?
目標是每個分割 1 到 10 GB。一個擁有十億列且每列 1 KB 的事實資料表總共是 1 TB — 每天一個分割 (1 TB) 是可行的,每月一個分割 (30 TB) 則太粗糙,每小時一個分割 (40 GB) 是合理的,但會使中繼資料開銷增加 24 倍。決策由兩個因素驅動:查詢如何過濾 (如果查詢總是指定某天,則按天分割即可;如果查詢有時指定週範圍,按天分割仍可,但按月分組也行),以及採用了什麼合併策略 (如果你定期合併小檔案,則按小時分割也是可行的)。考試常設局過度分割的反模式;分割不足則是較少見的錯誤。
延伸閱讀 — 分割與格式的官方 AWS 文件
權威的 AWS 來源包括《Athena 使用者指南》中關於分割、分割投影與單欄式儲存格式的章節、《Glue 開發人員指南》中關於 ETL 輸入與輸出的格式選項、《AWS 規範性指導:AWS 上的 Apache Iceberg》(這是 AWS 關於 Iceberg 採用的官方立場文件)、關於使用 Apache Iceberg 資料表的 Glue 文件、EMR 的 Apache Iceberg、Hudi 與 Delta Lake 發行版本指南,以及 Glue Schema Registry 文件。
AWS 大數據部落格有多篇關於 Iceberg 遷移、合併策略與分割投影模式的深入探討文章。AWS Well-Architected Analytics Lens 涵蓋了資料湖基礎,包括格式與分割選擇。Apache Iceberg 開源文件涵蓋了格式規格的深度內容,與 AWS 特定整合文件互補。Apache Parquet 規格文件涵蓋了列群組結構、統計資訊與壓縮 — 對於調校 Parquet 寫入器的工程師非常有用。最後,《AWS Glue 最佳實踐白皮書》涵蓋了 DynamicFrames 對比 DataFrames 以及與格式和分割決策交織在一起的檔案分組選項。