為什麼我們再次重構資料倉儲:PostHog 從 DuckDB 轉向 Trino 與 HogLake 的架構演進
SOURCE | 資訊源評估
- 準確性:高 - PostHog 基礎設施工程師 Benjamin Knofe-Vider 親筆撰寫的第一手生產環境(Dogf。
- 易理解性:高 - 捨棄行銷詞彙,直擊單機引擎雲端化、Catalog 元資料膨脹與 L4/L7 網路協定等底層痛點。
- 閱讀策略建議:精讀「DuckLake 相容性與規模化衝突」及「Postgres 協定擴展性困境」,理解開源組件跨入超大規模多租戶雲端服務時的架構斷裂點。
NAPKIN | 餐巾紙
- 一句話:單機分析引擎(DuckDB)與通用輕量級湖倉(DuckLake)在本地端表現完美,但在雲端多租戶 PB 級規模下,必。
- 餐巾紙公式: $$\text{雲端倉儲擴展性} = \frac{\text{分散式查詢調度 (Trino)} \times \text{無狀態協定路由 (HTTP)}}{\text{單機資源預估阻力} + \text{Catalog 全表統計掃描開銷} + \text{長連線狀態維護成本}}$$
公式白話解析:要把雲端資料倉儲做大做穩,不能把單機引擎硬搬上雲。必須用分散式引擎(Trino)搭配靈活的 HTTP 路由放大吞吐量;
- 行動觸發:盤點系統中是否存在「將單機工具直接包裝為多租戶雲端服務」或「以通用關聯式資料庫儲存高頻變更的 Lakehouse 。
餐巾紙草圖
┌──────────────────────────────────────────────────────────────
│ [過去:DuckDB + DuckLake + pgwire (單機思維雲端化)]
│ ├── 算力層:事前盲猜客戶 Worker 規格 -> OOM 溢寫磁碟或成本失控
│ ├── 儲存層:每次 Commit 重讀全 Catalog 統計 -> 單表寫入 > 3 分鐘
│ └── 網路層:Port 5432 有狀態長連線 -> NLB 負載均衡弱、方言相容黑洞
│
│ [現在:Trino + HogLake + HTTP (原生分散式雲端架構)]
│ ... (架構拓撲持續流轉)
│ └── 網路層:HTTP Header 靈活路由 (ALB/K8s) -> 無狀態高併發擴展
└──────────────────────────────────────────────────────────────
ROUND 1: SKELETON | 骨架掃描
“這篇文章在解決什麼根本問題”
- 核心問題:為何 PostHog 五個月前才為擺脫共用 ClickHouse 叢集的長查詢瓶頸與缺乏成本最佳化器(CBO)而改。
- 核心答案:DuckDB 雖是極致的單機分析引擎,但在雲端多租戶場景下,事前預測查詢資源(Worker Sizing)幾乎不可能;
- 論證結構:問題演進與實證反轉(回顧前次重構動機 -> 剖析單機引擎上雲的資源調度悖論 -> 揭露儲存層元資料在 PB 級規模。
章節骨架
- 單機王者上雲的水土不服(DuckDB is brilliant on one machine):探討單機引擎在本地端靠磁碟溢。
- 相容性與規模化的零和博弈(DuckLake is built for compatibility, not scale):剖。
- **網路協定與最終架構轉向(Speaking Postgres is harder than it sounds & Rebuild。
ROUND 2: DISSECTION | 血肉解剖
“憑什麼這麼說:論證與硬核證據”
論證鏈
┌──────────────────────────────────────────────────────────────
│ [前提1: 客戶查詢複雜度超預期,單機 DuckDB 需在查詢到達前預先決定 Worker 規格]
│ --> [前提2: 放大機器太貴、溢寫雲端磁碟太慢,且無法向用戶預告查詢所需 CPU/RAM]
│ --> [前提3: DuckLake 受限於跨 DB 通用 Schema,2PB/1530萬快照下每次寫入重讀全庫統計]
│ --> [前提4: 99% 統計資料屬已刪除表,清理後寫入快 30-50 倍但迅速復發,且 pgwire 難以擴展]
│ --> [結論: 必須放棄單機引擎與通用輕量 Catalog,轉向分散式 Trino + 專屬優化的 HogLake]
└──────────────────────────────────────────────────────────────
關鍵證據與量化數據
- Catalog 寫入延遲與垃圾膨脹數據:在 PostHog 規模下,單表寫入耗時超過 3 分鐘,因每次 Commit。
- Dogfooding 極限規模指標:PostHog 將自身全量資料放入 DuckLake 實測,下線遷移時總資料量達 **2。
- 時間與工程沉沒成本:距離上次從 ClickHouse 遷移至 DuckDB 僅過 5 個月,團隊便花費最近 3 個月 全面翻新架構;
隱形假設與邊界條件
- 隱形假設:原架構假設「多租戶隔離等於每客戶配發獨立單機 DuckDB 實例(Instance-per-tenant)」,且假。
- 邊界條件:當單一租戶資料量在 GB 級、快照在萬級以內且查詢模式固定時,DuckDB + DuckLake 仍是極佳低成本方案;
ROUND 3: SOUL | 靈魂提取
“如何落地與架構反思”
- 作者盲點:文章將 pgwire 失敗歸咎於協定與客戶端生態碎裂,卻忽略轉向 Trino + HTTP 後,原先主打「讓 db。
- 知識連接:印證分散式系統的 「抽象洩漏定律(Law of Leaky Abstractions)」——DuckDB/。
- 行動觸發:若正使用 Postgres 等關聯式資料庫作為 Lakehouse(如 Iceberg JDBC Catalog、。
留白提問 (Guided Reflection)
- 提問 1:雲端多租戶資料倉儲中,「每租戶獨立單機實例」與「多租戶共享分散式叢集」的黃金交叉點在哪裡?
- 架構師視角:關鍵在於 「工作負載峰谷比(Peak-to-Average Ratio)」 與 「資源預測可行性」。
- 提問 2:為何許多號稱「相容 Postgres 協定(pgwire)」的現代資料系統,最終都付出慘痛代價?
- 架構師視角:pgwire 不只是封包格式,背後隱含完整狀態機(Transaction 狀態、Session 變數、游標)與數。
跨域映射
- 在 雲端無伺服器運算(Serverless Computing),這叫 **冷啟動規格盲猜與垂直擴展天花板(Right-si。
- 在 作業系統與檔案系統(OS & File Systems),這叫 **Inode 元資料鎖定與垃圾碎片化(Metadata。
DEEP READ | 精讀指引 (Must-Read Segments)
[!IMPORTANT] 學習的本質需要「認知阻力」。請回到原文精讀以下核心技術段落:
- DuckDB is brilliant on one machine(單機引擎在雲端的資源預估死結)
- *「To run a single-node engine safely in the cloud, we have to size。
- 推薦理由:點破「萬物皆可 DuckDB」浪潮下的雲端落地盲區——在按量計費、講求 SLA 的雲端代管服務中,無法在查詢解析前。
- **DuckLake is built for compatibility, not scale(Catalog 元資料的 30~5。
- *「At our scale, a single-table write could take more than three mi。
- 推薦理由:展示當系統為維持「跨 SQL 資料庫通用相容」而放棄特定引擎底層優化時,元資料(Metadata)本身就會退化成比。
STRUCTURE MAP | 全書結構圖
┌──────────────────────────────────────────────────────────────
│ 為什麼 PostHog 再次重構資料倉儲 (從 DuckDB 轉向 Trino + HogLake)
│ ├── 1. 前情提要與轉折
│ │ ├── 5 個月前:棄 ClickHouse (無 CBO、長查詢崩潰) 轉投 DuckDB
│ │ └── 3 個月前:客戶負載超預期,決定徹底移除 DuckDB 重新架構
│ ├── 2. 算力層瓶頸:DuckDB 單機模型的雲端困境
│ │ ├── 優勢反轉:本地 Spill-to-disk 可靠,雲端掛載大磁碟卻又慢又貴
│ ... (架構拓撲持續流轉)
│ └── 開放表格式:自研 HogLake,通過 PB 級內部 Dogfooding 驗證
└──────────────────────────────────────────────────────────────
為什麼我們再次重構資料倉儲:PostHog 從 DuckDB 轉向 Trino 與 HogLake 的架構演進 (Architectural Deep Dive)
前言
五個月前,PostHog 為克服共用 ClickHouse 叢集執行數小時長查詢(Modeling Queries)時的資源排擠,以及缺乏基。
章節詳細總結
1. 算力調度悖論:單機引擎雲端化的資源預估與 I/O 瓶頸
DuckDB 核心哲學是在單節點榨乾硬體效能,記憶體不足(OOM)時靠磁碟溢寫(Spill-to-disk)確保查詢不崩潰。
┌──────────────────────────────────────────────────────────────
│ [單機引擎雲端調度死結]
│ 客戶提交複雜 SQL ──> 調度器被迫「事前盲猜」所需 CPU/RAM
│ ├── 猜太小 ──> 觸發雲端磁碟 Spill ──> 延遲暴增、查詢超時
│ └── 猜太大 ──> 啟動昂貴巨型 VM ──> 算力閒置、毛利遭侵蝕
│
│ [Trino 分散式彈性調度]
│ 客戶提交複雜 SQL ──> Coordinator 解析並切分為細粒度 Splits
│ └── 動態分發至共享 Worker 叢集 ──> 水平吸收突發負載
└──────────────────────────────────────────────────────────────
架構權衡 (Trade-offs)
- 優勢 (Pros):單機引擎架構極簡、無跨節點網路 Shuffle 開銷,資料集能塞入單機記憶體時性價比極佳。
- 劣勢與成本 (Cons & Overheads):缺乏執行期跨節點動態擴展能力,雲端防範 OOM 的過度配置(Over-pr。
- 選型建議:工作負載可預測、單次掃描在數十 GB 內或 CI/CD 測試首選 DuckDB;
2. 儲存與元資料危機:DuckLake 在 1 兆列規模下的 Catalog 崩潰
PostHog 將全量生產資料投入 DuckLake 進行 Dogfooding。當規模達 2 PB、1 兆列、1,530 萬個快照。
-- 模擬 DuckLake 在高頻快照下的元資料退化情境
-- 每次 Commit 觸發全範圍統計掃描,其中 >99% 為已刪除表的殘留紀錄
SELECT table_id, column_stats, row_count
FROM ducklake_catalog_statistics
WHERE catalog_version <= CURRENT_SNAPSHOT();
-- 缺乏高效 Partition Pruning 與非同步 GC,導致單次寫入鎖定並耗時 > 180 秒
架構權衡 (Trade-offs)
- 優勢 (Pros):以標準關聯式 DB 儲存 Lakehouse 元資料,支援 ACID 交易且中小型規模極易部署備份。
- 劣勢與成本 (Cons & Overheads):千萬級快照與高頻寫入下,B-Tree 索引膨脹、MVCC 死元組與跨表統計。
- 選型建議:中小團隊必須配置積極的 Snapshot Expiration 與 Orphan Statistics GC 並以。
3. 網路傳輸與協定層重構:為什麼放棄 pgwire 轉向 HTTP 與 Trino
起初透過 Port 5432 提供 pgwire 看似能無痛銜接 BI 與 dbt 工具,實則在雲端規模化運維中帶來三大災難:
┌──────────────────────────────────────────────────────────────
│ [舊架構:pgwire (Port 5432 TCP 長連線)]
│ 多樣化 PG Clients ──> AWS NLB (L4 僵化轉發) ──> 狀態化連線維持 (高成本)
│ └── 痛點:TTL/Idle 管理困難、缺乏 Header 路由、無止盡的 Client 方言修補
│
│ [新架構:HTTP/REST 協定 + Trino + HogLake]
│ 標準化客戶端 ──> AWS ALB / K8s Ingress (依 HTTP Header 精準路由)
│ └── 優勢:無狀態短連線高併發、雲端原生負載均衡、擺脫 PG 相容性泥淖
└──────────────────────────────────────────────────────────────
架構權衡 (Trade-offs)
- 優勢 (Pros):HTTP 查詢協定完美契合現代雲端基礎設施(ALB、Envoy、K8s),實現 Header 多租戶路由與零成本閒置連線管理。
- 劣勢與成本 (Cons & Overheads):外部工具(dbt、BI)須改用專屬 Trino Adapter 或驅動,增加初期遷移設定成本。
- 選型建議:除非定位是「100% OLTP Postgres 替代品」,否則建構雲端 OLAP 倉儲切勿自行維護 pgwire 協定層;
總結與結論
- 本地端與雲端多租戶的架構鴻溝不可忽視:單機優雅的技術(DuckDB 記憶體管理與磁碟溢寫),放到需事前動態分配資源、按量計費。
- 元資料(Metadata)擴展性決定湖倉真實上限:在 PB 級與千萬級快照下,依賴「全庫統計重讀」或缺乏強大自動化 GC 的。
- 拒絕相容性泥淖,擁抱雲端原生無狀態協定:果斷捨棄維護高昂的 pgwire 長連線與私有 Fork,轉向與 K8s、HTTP 。
Source URL: https://x.com/posthog/status/2117351603514793997