Firexport部落格

Firestore Enterprise 與 Standard:新應用程式請從 Enterprise 開始

建立 Firestore 資料庫時選擇的版本(Standard 或 Enterprise)之後無法變更。Enterprise 版的 Native 模式已在 2026 年 4 月正式推出(GA),現在新應用程式從 Enterprise 開始比較划算。前提是你要自己負責索引和用戶端存取。

重點整理

  • 選之後比較不會卡住的那一個。Standard 的限制只能靠搬移資料解決,Enterprise 的問題大多部署一個索引就能解決。原因
  • 程式碼不變,查詢更多。即時監聽器、離線和安全性規則與 Standard 相同,還多了能做搜尋、匯總和聯結的 Pipeline 查詢。多了什麼
  • 有索引的讀取更便宜。以 ID 讀取 4 KiB 以內的文件,費用是 Standard 的六分之一。寫入的索引越多越貴,刪除則一律比較貴。價格比較
  • 索引和存取要自己負責。沒有索引的查詢不會報錯,而是讀取整個集合,別人也能故意這麼做。要做的事

為什麼預設選 Enterprise

1. 無法變更,所以選比較不會卡住的那一個

版本在建立資料庫時決定,之後不會改變。要變更,就得把資料搬到新的資料庫、重新建立索引、TTL 和備份設定,並發布新版應用程式,讓它連到新的資料庫(遷移指南)。

所以應該從之後比較不會卡住的那一邊開始。在 Standard 上卡住的是搜尋、匯總、聯結這類功能,只能靠遷移或改結構來繞過。在 Enterprise 上卡住的大多是缺少索引,程式碼和資料都不必動,部署索引就好。

2. 同樣的程式碼,更多的查詢

Enterprise 的 Native 模式使用和 Standard 相同的 Firebase SDK 與相同的查詢(Core 作業)。where()、orderBy()、onSnapshot() 監聽器、離線快取和安全性規則照常運作,也支援本機模擬器、Cloud Functions(第 2 代)觸發條件、與 Standard 相同的區域,以及 Spark 方案的免費用量。不同的是排序:排序值相同的文件之間不會依文件 ID 排列,所以如果用游標分頁,請在 orderBy 加上文件 ID。

在這之上還有 Pipeline 查詢。在 Standard 上需要變通的事,變成一個查詢。

想做的事StandardEnterprise
全文搜尋同步到外部搜尋服務(Algolia 等)文字搜尋
找出半徑內的地點建立 geohash 欄位做範圍查詢地理空間搜尋
以部分字串或規則運算式比對只能前綴比對str_contains、regex_match
分組合計、不重複值的數量逐組匯總,或維護計數器文件一個 aggregate 階段
合併讀取其他集合反正規化,或讀取多次子查詢聯結
批次更新、刪除符合條件的文件先讀取再分批寫入的指令碼update、delete 階段
防止值重複以該值為 ID 的文件加上交易唯一索引

文字搜尋、地理空間搜尋和批次更新刪除(DML)已在 2026 年 10 月正式推出。不過 Pipeline 是執行一次就結束的讀取,沒有即時監聽和離線支援,安全性規則在 Pipeline 中也只認得與常數比較的簡單篩選條件。畫面上的清單和即時更新用 Core 查詢,搜尋、匯總和報表用 Pipeline,複雜的 Pipeline 放到伺服器上(Admin SDK、Cloud Functions)執行。

3. 有索引的讀取更便宜

Standard 依文件數量計費,Enterprise 依讀寫的位元組計費。以下是 us-central1 在 2026 年 11 月的價格。

StandardEnterprise
讀取每百萬份文件 US$0.30每 4 KiB 1 個單位,每百萬單位 US$0.05
寫入每百萬份文件 US$0.90,索引更新免費每 1 KiB 1 個單位,每百萬單位 US$0.26;每個索引項目另加 1 個單位
刪除每百萬份文件 US$0.10以寫入單位計(文件 + 索引項目)
即時更新以讀取計,每百萬次 US$0.30每 4 KiB 1 個單位,每百萬單位 US$0.30;4 KiB 以內的文件價格相同
儲存空間每 GiB 每月約 US$0.15,所有欄位的自動索引也計入每 GiB 每月約 US$0.23,只計入你建立的索引
每日免費用量讀取 5 萬、寫入 2 萬、刪除 2 萬讀取 5 萬、寫入 4 萬、即時更新 5 萬單位
  • 讀取:以 ID 讀取 4 KiB 以內的文件,Enterprise 只要六分之一,24 KiB 以內也相同或更便宜。查詢還要加上讀取索引的費用,結果只有 1 筆時是三分之一,結果越多越接近六分之一。
  • 寫入:新寫入 1 KiB 的文件時,索引項目不超過 2 個,Enterprise 比較便宜(每百萬次 US$0.78),3 個起就比較貴(US$1.04)。變更有索引欄位的更新,每個變動的項目要 2 個單位,所以更快變貴。
  • 刪除:最小的文件也要 1 個單位(US$0.26),所以一律比 Standard(US$0.10)貴。

讀取遠多於寫入的應用程式,用 Enterprise 比較便宜。寫入和刪除多的應用程式,請先用自己的文件大小和索引數量算一算。

代價:索引和存取要自己負責

Standard 只執行能使用索引的查詢。每個欄位都會自動建立索引,需要複合索引的查詢會回傳錯誤,並附上建立該索引的連結。所以查詢費用只跟結果數量有關。

Enterprise 不會自動建立索引,沒有索引也會執行查詢。代價是讀取整個集合並依讀取的位元組計費;排序也在記憶體中進行,可能碰到每個查詢的記憶體上限(128 MiB)。因為不會報錯,開發時只有幾十份文件看不出來,資料變多才會浮現。

以下是以使用者名稱找 1 位使用者的查詢執行一百萬次的費用。文件大小 2 KiB,第一列是 Google 的定價範例,第二列把同樣的計算擴大到 10 萬份文件。

集合Standard(自動索引)Enterprise(有索引)Enterprise(無索引)
100 份文件US$0.30US$0.10US$2.50
10 萬份文件US$0.30US$0.10US$2,500

一個索引讓同一個查詢的費用相差 2.5 萬倍(100,000 × 2 KiB ÷ 4 KiB = 每次查詢 50,000 個單位)。

別人也能利用這個差距。只要用戶端能列出某個集合,任何人都可以加上一個針對無索引欄位的篩選條件,讓 Firestore 掃描他能讀取的整個範圍。沒有符合的文件,所以 limit 也沒用;安全性規則也擋不住額外加在查詢上的篩選條件。在 Standard 上,這樣的查詢只會回傳錯誤。

四件要做的事

  1. 寫查詢時,順手寫索引。對持續成長的集合,每種 where、orderBy 組合都在 firestore.indexes.json 寫好索引,再用 firebase deploy --only firestore:indexes 部署。Standard 以前自動建立的單一欄位索引也要自己寫。以文件 ID 讀取不需要索引。下面是 where('authorId', '==', uid).orderBy('createdAt', 'desc') 對應的索引。
    {
      "indexes": [
        {
          "collectionGroup": "posts",
          "queryScope": "COLLECTION",
          "fields": [
            { "fieldPath": "authorId", "order": "ASCENDING" },
            { "fieldPath": "createdAt", "order": "DESCENDING" }
          ]
        }
      ]
    }
  2. 上線前用 Query Explain 檢查。在 Firebase 控制台 Firestore 的資料(Data)分頁,用查詢編輯器(Query Editor)以相同條件執行查詢,再打開 Query Explain 分頁。如果執行樹的最底層是 TableScan,就是沒用索引、讀取了整個集合。
  3. 收緊用戶端存取。強制啟用 App Check,拒絕不是來自你應用程式的要求;用安全性規則把清單讀取限定在有索引欄位的相等條件,例如 resource.data.ownerId == request.auth.uid。這樣即使有人觸發掃描,也只會在該使用者的文件範圍內結束。
  4. 開啟 Query Insights 和預算快訊。Query Insights 會顯示常用的查詢及其效能,幫你找出需要索引的地方。如果使用 Blaze 方案,也請設定 Cloud Billing 預算快訊。

從 Enterprise 開始

在 Firebase 控制台的 Firestore 中點選建立資料庫(Create database),選擇 Enterprise 和 Native 模式,再設定 ID 和位置。即時更新(Realtime Updates)請保持開啟(預設值)。它之後無法變更,關閉後建立的資料庫就不能使用監聽器。接下來有三點和 Standard 不同。

  1. 在程式碼中傳入資料庫 ID。Enterprise 資料庫是你自己命名的資料庫,(default) 只有 Standard 才有。SDK 預設會連到 (default),除非另外指定。
    // Web
    const db = getFirestore(app, 'app-db');
    
    // Android (Kotlin)
    val db = FirebaseFirestore.getInstance("app-db")
    
    // iOS (Swift)
    let db = Firestore.firestore(database: "app-db")
    
    // Flutter
    final db = FirebaseFirestore.instanceFor(
        app: Firebase.app(), databaseId: 'app-db');
  2. 在 firebase.json 寫明資料庫和版本。這樣規則和索引會部署到該資料庫,模擬器也會以 Enterprise 啟動。請先在控制台建立資料庫。如果寫明的資料庫不存在,firebase deploy 會代為建立,而 Firebase CLI 15.12 這時會建立成 Firebase SDK 無法使用的 MongoDB 相容模式。
    {
      "firestore": {
        "database": "app-db",
        "edition": "enterprise",
        "rules": "firestore.rules",
        "indexes": "firestore.indexes.json"
      }
    }
  3. 免費用量只會給第一個建立的資料庫。如果專案裡有沒在用的 Standard 資料庫,請先刪除它,再建立 Enterprise 資料庫,免費用量才會歸到 Enterprise。

Standard 仍然比較合適的情況

  • 已經在 Standard 上執行的應用程式。在真正需要 Pipeline 之前不要遷移。
  • 沒有人負責查詢和索引的專案。不執行無索引查詢的 Standard 就是安全網。
  • 用戶端直接讀取大型公開集合的應用程式。無法用規則縮小範圍的公開清單,任何人都能觸發整個集合的掃描。
  • 寫入和刪除很多,或主要讀取大型文件的應用程式。超過上面的損益平衡點,Standard 比較便宜。
  • 需要使用以 (default) 資料庫或 Cloud Functions 第 1 代為前提的工具時。Enterprise 是具名資料庫,也不支援第 1 代觸發條件。

資料來源

所有文章 →