資料要存在哪:儲存的階層與抽象,讀《Fundamentals of Data Engineering》Ch.6
· tech
上一篇講資料從源頭生出來。生出來之後第一件事就是:存去哪? 這章談儲存 —— 而它最反直覺的一點是:儲存不是「一個東西」,而是一整條從奈秒到小時、從天價到白菜價的階層。 看懂這條階層,後面所有「該放哪、放多久、花多少」的決定才有依據。
儲存是一條階層,不是一個選項
書從最底層的物理材料往上疊:CPU 快取、RAM、SSD、HDD、物件儲存、冷儲存。它們的差別不是「好壞」,而是同一組取捨的不同落點 —— 越快的越貴、容量越小;越便宜的越慢、容量越大。中間單價和延遲各差好幾個數量級。
這條階層也是快取(cache)的原理:把熱資料往上搬(快、貴),冷資料留在下面(慢、便宜)。Spark 把資料 cache 進記憶體、資料庫用 RAM 當 buffer,都是同一招 —— 拿貴的空間換速度。
對資料工程最重要的一層:物件儲存
上層那些(RAM、SSD)多半被資料庫、引擎藏在底下,你不太直接碰。DE 真正天天面對的是系統層的儲存,快速對照三種:
| 型態 | 像什麼 | 典型用途 |
|---|---|---|
| 檔案儲存 | 一般檔案系統、資料夾 | 開發、小量、掛載 |
| 區塊儲存 | 一顆裸硬碟(EBS) | 資料庫 / VM 的底層 |
| 物件儲存 | 一個超大 key-value 倉庫 | 海量非結構化資料 |
三者裡的主角是物件儲存(S3、GCS、Azure Blob),現代資料湖幾乎都建在它上面,書也花最多篇幅在它。它憑什麼?幾乎無限擴充、按用量計費超便宜、物件不可變(適合當可重播的原始層),而且天生與運算分離。 最後這點,牽出這章最大的主題。
這章最大的主題:運算與儲存分離
傳統資料庫或 Hadoop,運算和儲存綁在同一台機器上 —— 想加算力,連硬碟一起加;想加容量,連 CPU 一起加,兩邊永遠一起伸縮,結果常常一邊爆滿、一邊閒置。雲時代把它拆開了:
這一拆,解釋了近十年一堆架構為什麼長這樣:資料一份放在物件儲存,要跑 Spark 就開一批 executor pod、要下 SQL 就叫一個查詢引擎,算完全部關掉、只留資料。你不再為「尖峰時要多少算力」養一整年的機器,也不再因為資料變多就被迫加 CPU。Spark 那套 driver/executor 按需伸縮、lakehouse、serverless 查詢,地基全是這一條。
但別誤會:綁在一起有時才是對的
分離贏的是「彈性、成本、湖」這類工作負載,不是全部。MPP 資料庫(Greenplum、Teradata、傳統 Redshift)刻意把運算和儲存綁死,而且綁得有道理:每個 segment 節點用本機磁碟存自己那片資料、就地運算,靠 distribution key 讓 join 在本機發生、不用跨網路重分佈。它換到的是分離模型給不了的穩定低延遲與高併發 —— BI dashboard、有 SLA 的查詢、大量複雜 join,本機碟加深度整合的 optimizer 很難被打敗。
| 綁在一起(MPP) | 分離(物件儲存 + 彈性運算) | |
|---|---|---|
| 最佳化 | 穩定低延遲、高併發 | 彈性、閒置成本、獨立伸縮 |
| 資料在地性 | 天生就有 | 靠快取補回來 |
| 痛點 | 關不掉、加節點要重分佈、冷資料佔著貴運算 | 網路延遲、要靠快取續命 |
而且界線正在靠快取收斂:分離陣營用本機 NVMe 快取熱資料(Snowflake local cache、Databricks disk cache),把在地性事後補回來。大家真正在搶的都是資料在地性——MPP 天生擁有,lakehouse 事後補到。實務上更常見的是兩個都用:湖放海量原始/冷資料,MPP 或倉儲當高併發的服務層,正好對上下一節的抽象分層與資料溫度。
三種資料工程的儲存抽象
在物件儲存這塊地基之上,DE 面對的是三個高層抽象。它們的差別在 Medallion 那篇也碰過,這裡用一張表釘清楚:
| 抽象 | 一句話 | schema 時機 |
|---|---|---|
| 資料倉儲(Warehouse) | 結構化、為分析最佳化 | schema-on-write(進來就得對格式) |
| 資料湖(Lake) | 什麼都先丟進來的原始池 | schema-on-read(讀的時候才套結構) |
| 資料湖倉(Lakehouse) | 湖的彈性 + 倉的管理 | 兩者合流(在湖上加 ACID、schema) |
演進的方向很清楚:湖太亂(什麼都丟、難治理)、倉太硬(貴、只吃結構化),lakehouse 想兩邊的好處都要 —— 在便宜的物件儲存上,補回交易保證與結構管理。
資料是有溫度的:冷熱分層與保存期限
最後一個實用概念:資料溫度。不是所有資料都該放在同一層。
- 熱(hot):常被查,放快的層(SSD / 記憶體 / 標準物件儲存),貴但快。
- 溫(warm):偶爾查,放便宜一點的層。
- 冷(cold):幾乎不查、但為了合規或備份得留,丟進封存(冷儲存),最便宜、取用最慢。
搭配的是保存期限(retention):資料不是存了就永遠留著,而該有生命週期 —— 什麼時候降溫、什麼時候刪。這既是省錢(別讓冷資料佔著貴的層),也是合規(該刪的要刪)。跟 Kafka 的 retention / compaction是同一種思維:儲存要主動管理,不是無限堆積。
反思
「運算與儲存分離」讓我學會的,其實是看工作負載選邊
這章把一個我天天在用、卻沒歸納成一句話的東西講白了。以前資源就是一台台「CPU 配硬碟」的機器,一起買、一起閒置;分離之後,資料放物件儲存、運算按需長出來,成本結構整個變了 —— 沒作業時幾乎不花運算錢,尖峰時才把 executor 開滿。我寫 Spark 部署、Spark on K8s 那兩篇反覆講的「用完即刪」,追根究柢就是這條原理的落地。
但我一度把它當成「進步 vs 落後」,是被一個反例修正的:很多人用 Greenplum,還是把運算放進 DB,而且是對的。高併發、要穩定低延遲的服務型查詢,MPP 那種「資料就在本機、就地運算」反而更快 —— 綁在一起不是守舊,是為在地性做的取捨。所以我現在的判斷不是「預設分離」,而是先看工作負載:彈性、成本敏感、冷資料多 → 分離;高併發、要穩延遲 → 綁在一起(或分離再靠快取把在地性補回來)。這跟 Ch.4「先架構後工具、每個選擇都是取捨」是同一句話 —— 分離是強大的預設,不是萬用的答案。
我押注的儲存地基,還是物件儲存
回頭看 Ch.4講的「賭在不變的地基上」,儲存這層我下的注很一致:原始資料一律先落物件儲存,不可變、可重播,再讓上面的引擎自由來去。這跟 Medallion 守著 Bronze 不可變是同一個決定的兩面。物件儲存便宜到「先存了再說」幾乎不痛,而它十年後大概還在 —— 把最重要的資產放在最穩、最便宜的一層,是我越做越安心的選擇。
資料溫度這件事,我是被帳單教會的
「冷熱分層」聽起來很基本,但我真正開始認真管,是被雲端儲存帳單嚇到之後。一堆一年被查不到一次的舊資料,躺在標準層按天燒錢。後來把生命週期規則設起來(自動降溫、自動封存、過期清掉),帳單立刻瘦一圈。教訓是:儲存的成本不在「存」,在「忘了管」。 現在我建任何資料層,retention 與分層規則會跟資料本身一起設計,而不是等帳單爆了才回頭補 —— 這跟我對 工具的態度一樣,主動設計取捨,別讓預設值替你決定成本。