# 策展 · X (Twitter) 🔥

> 作者：Supabase (@supabase) · 平台：X (Twitter) · 日期：2026-05-14

> 原始來源：https://x.com/supabase/status/2054544501121679398

## 中文摘要

# Realtime 還是 ETL？如何選擇正確的工具

Supabase Realtime 和 Supabase ETL 都會讀取你 Postgres 資料庫中的變更。它們在底層都使用了邏輯複製（logical replication）。如果你稍微瞇著眼看，它們看起來甚至很像。但它們解決的是截然不同的問題，選錯工具會讓你感到挫折。

這篇文章將解釋這兩項產品的功能、它們的差異，以及你該在什麼時候選擇哪一個。

## 兩個工具，兩種任務

最簡單的理解方式如下：

- **Realtime** 會在資料庫變更發生的當下，立即將這些變更發送到使用者的瀏覽器和應用程式。它是為即時體驗而設計的。

- **ETL** 會以近乎即時的方式，將資料庫變更發送到 BigQuery 和 Analytics Buckets 等分析目的地。它是為可靠的資料傳輸而設計的。

Realtime 回答的問題是：「我該如何向使用者展示剛剛發生了什麼？」

ETL 回答的問題是：「我該如何將生產環境的資料匯入我的分析資料倉儲？」

如果你搞混了這兩者，就會遇到問題。我們經常看到這種情況發生，而這篇文章的其餘部分將幫助你避免重蹈覆轍。

## Realtime 的功能

Supabase Realtime 在一個產品中整合了三項功能：

1. **Broadcast（廣播）**：在已連線的客戶端之間即時發送訊息。不需要資料庫。想像一下游標位置、輸入狀態指示器或遊戲狀態。

2. **Presence（在線狀態）**：追蹤誰在線上以及他們正在做什麼。同樣不需要資料庫。想像一下「有 3 位使用者正在編輯此文件」或「Jane 正在輸入...」。

3. **Postgres Changes（Postgres 變更）**：監聽資料庫資料表上的 INSERT、UPDATE 和 DELETE 事件，並透過 WebSocket 將其傳遞給已訂閱的客戶端。

這三項功能中的兩項（Broadcast 和 Presence）可以在完全不與資料庫互動的情況下運作。客戶端對客戶端的 Broadcast 純粹透過 WebSocket 發送訊息，不會儲存任何內容。然而，「來自資料庫的 Broadcast」允許你透過觸發器（triggers）從資料庫變更中觸發廣播，讓你能夠控制哪些事件會傳送到哪些頻道。這一點很重要，因為 Realtime 不僅僅是一個資料庫變更監聽器，它還是你應用程式的即時通訊層。

## Postgres Changes 如何運作

當客戶端訂閱某個資料表時，Realtime 會使用 PostgreSQL 複製槽（replication slot）從預寫式記錄（Write-Ahead Log, WAL）中讀取變更。對於每一項變更，它都會針對每一位訂閱的使用者檢查列層級安全性（Row Level Security, RLS）原則。如果使用者被授權查看該變更，Realtime 就會透過他們的 WebSocket 連線將其發送出去。

這是為即時 UI 更新而設計的。當使用者在聊天資料表中插入一則訊息，其他使用者會立即看到它出現。當儀表板資料表中的一行資料更新時，圖表會自動重新整理。

## Realtime 不保證的事項

Realtime 的 Postgres Changes 功能並不保證送達。如果客戶端斷線 30 秒後重新連線，這 30 秒內發生的變更就會遺失。Realtime 不會將它們排入佇列，也不會追蹤每個客戶端讀取到了什麼進度。

Broadcast Replay 為「來自資料庫的 Broadcast」訊息提供了有限的補救機制：客戶端可以使用 `since` 時間戳記，請求過去 3 天內最多 25 則訊息。但這僅適用於私人頻道，僅適用於資料庫來源的廣播，且目前處於公開 Alpha 階段。它並非適用於所有 Realtime 事件的通用重播機制。

Postgres Changes 使用臨時複製槽。當沒有客戶端訂閱時，它會完全停止複製資料。當客戶端再次訂閱時，會建立一個新的複製槽。

Realtime 團隊刻意這樣設計。保證送達需要持久的狀態追蹤、訊息佇列和確認協定。這些機制會增加延遲和複雜性，反而會讓 Realtime 在執行其核心任務（盡可能快地傳遞即時更新）時表現變差。

如果你需要確保每一項變更都能準確抵達目的地，無論發生什麼情況，Realtime 都不是正確的工具。

## ETL 的功能

Supabase ETL 是一個變更資料擷取（Change Data Capture, CDC）管線。它會讀取你 Postgres 資料表中的每一項 INSERT、UPDATE、DELETE 和 TRUNCATE 操作，並將它們寫入目的地。目前支援的目的地包括 Analytics Buckets（基於 Apache Iceberg 建構）和 BigQuery。

ETL 以近乎即時的方式 1 對 1 複製你的資料。如果你的目的地斷線或出現問題，ETL 不會跳過任何資料。

## ETL 如何運作

當你建立一個 ETL 管線時，它會透過永久複製槽連線到你的資料庫。首先，它會對你現有的資料進行完整備份。接著，它會切換到串流模式，並在變更發生的當下擷取每一項變更，延遲時間通常在毫秒到秒之間（取決於設定參數、資料大小和目的地類型）。

值得注意的是，Supabase ETL 不會遵循列層級安全性（RLS）。Supabase ETL 會讀取每一筆資料。如果你需要篩選資料，應該使用發布篩選器（publication filters）。

變更會被批次處理並寫入你的目的地。如果管線崩潰，它會從最後確認的位置重新啟動。不會遺失任何資料變更。請注意，結構描述變更（新增或移除欄位）不會自動傳播，需要手動處理。

## ETL 保證的事項

ETL 提供「至少一次」（at-least-once）的送達保證。資料庫中發生的每一項變更都會至少抵達目的地一次。在極少數情況下（例如在長時間運行的交易中發生崩潰），變更可能會被傳遞超過一次。目的地會處理「僅一次」（exactly-once）的處理邏輯。有些目的地（如 BigQuery）會自動進行去重，而有些則可能不會。

ETL 使用永久複製槽。這意味著 Postgres 會保留 WAL 資料，直到 ETL 確認已完成處理。如果你為了維護而停止管線並稍後重新啟動，它會從上次中斷的地方繼續執行。請注意，當管線暫停時，Postgres 會持續保留 WAL 資料。長時間的暫停可能導致磁碟空間顯著增加，且根據你的 Postgres 設定，如果超過了 WAL 保留限制，管線可能會失敗。

這與 Realtime 的做法截然不同。ETL 以速度換取可靠性。它可能無法在變更發生的同一毫秒內將其傳遞到你的資料倉儲，但它保證會傳遞每一項變更。

## 關鍵差異

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1778726523052-diaHIKhYQjWcAAbTtpng.png)

## 資料流向

Realtime 透過 WebSocket 連線將資料發送到客戶端應用程式。使用者的瀏覽器和行動裝置端是目的地。

ETL 將資料發送到分析系統。BigQuery、Analytics Buckets 以及未來其他的資料倉儲都是目的地。

這些是本質上完全不同的目標，且有著本質上不同的需求。客戶端應用程式需要低延遲，而分析系統需要完整性。

## 資料庫依賴性

Realtime 的 Broadcast 和 Presence 功能可以在不接觸資料庫的情況下運作。你可以建構完整的協作體驗（游標、在線狀態指示器、臨時訊息），而無需編寫任何資料庫查詢。然而，「Postgres Changes」和「來自資料庫的 Broadcast」都需要資料庫互動。

ETL 完全由資料庫驅動。它移動的每一個位元組資料都來自你的 Postgres 資料表。

## 擴展特性

Realtime 的 Broadcast 和 Presence 功能是為高吞吐量和低延遲而建構的。它們不會針對每個訂閱者執行資料庫查詢，並且在大量併發連線下具有良好的擴展性。

Postgres Changes 的運作方式則不同。它會依序處理變更以維持順序。對於每一項變更，它都會針對每個訂閱的客戶端執行 RLS 授權檢查。如果有 100 個訂閱者正在監看一個資料表，單次 INSERT 就會產生 100 次授權查詢。這是一個刻意的設計選擇，旨在為典型工作負載優先考慮正確性和低延遲，而非原始吞吐量。

ETL 則以可調式平行處理的批次來處理變更。它不需要授權個別使用者，因為它是在將資料移動到系統，而不是發送給終端使用者。

## 何時使用 Realtime

當你需要向使用者推送即時更新時，請使用 Realtime：

- **聊天應用程式**：訊息會立即出現在所有參與者的畫面上。
- **協作編輯**：即時查看其他使用者的游標和變更。
- **即時儀表板**：圖表和指標無需重新整理頁面即可更新。
- **通知**：當相關事件發生時提醒使用者。
- **多人遊戲功能**：同步遊戲狀態或共享體驗。
- **在線狀態追蹤**：顯示誰在線上、誰正在輸入、誰正在查看文件。

共同點：有人正在觀看，且需要即時看到變更。

## 何時使用 ETL

當你需要將資料可靠地傳輸到分析系統時，請使用 ETL：

- **分析與報表**：將生產資料移動到 BigQuery 或 Iceberg 進行查詢，而不會影響你的生產資料庫。
- **稽核軌跡**：Analytics Buckets 會儲存每一項 INSERT、UPDATE 和 DELETE 的僅附加（append-only）變更日誌。不會遺失任何資料。
- **資料倉儲**：將你的營運資料複製為針對分析查詢最佳化的欄位格式。
- **合規性**：維護所有資料變更的完整、可驗證的歷史記錄。
- **機器學習管線**：在不查詢生產資料庫的情況下，為訓練或特徵儲存（feature stores）提供最新資料。
- **工作負載隔離**：針對你的資料倉儲執行繁重的分析查詢，而不是針對生產資料庫。

共同點：系統需要一份完整、可靠的資料副本。

## 我們最常看到的錯誤

有些開發者發現了 Realtime 的 Postgres Changes 功能，便心想：「我可以用這個將資料從一個系統複製到另一個系統。」他們用 `supabase-js` 寫了 20 行程式碼，訂閱資料表變更，並將其導向另一個系統。

這在開發階段運作得很好。甚至在生產環境中也能運作一段時間。然後，某個 WebSocket 連線中斷了幾秒鐘，資料就遺失了。或者訂閱程序重新啟動，錯過了一批變更。又或者負載激增，導致依序進行的 RLS 授權檢查跟不上速度。

問題不在於 Realtime 壞了，而在於 Realtime 本身就不是為這項工作設計的。

如果你要將資料庫變更導向另一個系統，且你需要確保每一項變更都能抵達，請使用 ETL。那才是它被建構出來的目的。

## 我可以兩者並用嗎？

可以。事實上，許多應用程式都應該這樣做。

考慮一個電子商務平台。你可能會使用 Realtime 即時向客戶推送訂單狀態更新（「你的訂單已出貨！」）。同時，你使用 ETL 將所有訂單資料複製到 BigQuery，用於每日銷售報表和趨勢分析。

同一個資料庫。同一個資料表。針對不同任務使用不同的工具。

Realtime 處理即時體驗，ETL 處理分析管線。各司其職。

![](https://pub-75d4fe1e4e80421b9ecb1245a7ae0d1a.r2.dev/curated/1778726522917-iaHIKhzlXWoAAMjKlpng.png)

## 開始使用

Supabase Realtime 可在所有 Supabase 專案中使用。請查看 [Realtime 文件](https://supabase.com/docs/guides/realtime)以開始使用。

Supabase ETL 目前處於私人 Alpha 階段。你可以透過 Supabase Dashboard 申請存取權限，或聯絡你的客戶經理。閱讀 [ETL 部落格文章](https://supabase.com/blog/supabase-etl)以了解更多運作細節。

## 標籤

教學資源, 其他, Supabase, Postgres
