Firestore Enterprise 与 Standard:新应用请从 Enterprise 开始
创建 Firestore 数据库时选择的版本(Standard 或 Enterprise)之后无法更改。Enterprise 版的 Native 模式已于 2026 年 4 月正式发布(GA),现在新应用从 Enterprise 开始更划算。前提是你自己负责索引和客户端访问。
要点
为什么默认选 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 上需要变通的事,变成一条查询。
| 想做的事 | Standard | Enterprise |
|---|---|---|
| 全文搜索 | 同步到外部搜索服务(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 月的价格。
| Standard | Enterprise | |
|---|---|---|
| 读取 | 每百万个文档 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.30 | US$0.10 | US$2.50 |
| 10 万个文档 | US$0.30 | US$0.10 | US$2,500 |
一个索引让同一条查询的费用相差 2.5 万倍(100,000 × 2 KiB ÷ 4 KiB = 每次查询 50,000 个单位)。
别人也能利用这个差距。只要客户端能列出某个集合,任何人都可以加上一个针对无索引字段的过滤条件,让 Firestore 扫描他能读取的全部范围。没有匹配的文档,所以 limit 也没用;安全规则也拦不住在查询上额外添加的过滤条件。在 Standard 上,这样的查询只会报错。
四件要做的事
- 写查询时,顺手写索引。对持续增长的集合,每种
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" } ] } ] } - 上线前用 Query Explain 检查。在 Firebase 控制台 Firestore 的数据(Data)标签页中,用查询编辑器(Query Editor)以相同条件执行查询,然后打开 Query Explain 标签页。如果执行树最底层是
TableScan,就是没用索引、读取了整个集合。 - 收紧客户端访问。强制启用 App Check,拒绝不是来自你应用的请求;用安全规则把列表读取限定在有索引字段的相等条件上,例如
resource.data.ownerId == request.auth.uid。这样即使有人触发扫描,也只会在该用户的文档范围内结束。 - 打开 Query Insights 和预算提醒。Query Insights 会显示常用查询及其性能,帮你找出需要索引的地方。如果用的是 Blaze 方案,也请设置 Cloud Billing 预算提醒。
从 Enterprise 开始
在 Firebase 控制台的 Firestore 中点击创建数据库(Create database),选择 Enterprise 和 Native 模式,再设定 ID 和位置。实时更新(Realtime Updates)请保持开启(默认值)。它之后无法更改,关闭后创建的数据库就不能使用监听器。之后有三点与 Standard 不同。
- 在代码中传入数据库 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'); - 在 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" } } - 免费用量只给第一个创建的数据库。如果项目里有不用的 Standard 数据库,请先删除它,再创建 Enterprise 数据库,这样免费用量才会归 Enterprise。
Standard 仍然更合适的情况
- 已经在 Standard 上运行的应用。在真正需要 Pipeline 之前不要迁移。
- 没有人负责查询和索引的项目。不执行无索引查询的 Standard 就是安全网。
- 客户端直接读取大型公开集合的应用。无法用规则缩小范围的公开列表,任何人都能触发全集合扫描。
- 写入和删除很多,或主要读取大文档的应用。超过上面的平衡点,Standard 更便宜。
- 需要使用以
(default)数据库或 Cloud Functions 第 1 代为前提的工具时。Enterprise 是命名数据库,也不支持第 1 代触发器。
资料来源
- Firestore 版本、Native 模式的版本比较、Enterprise Native 模式概览:功能、索引、排序和扫描的差异
- Enterprise 价格、查询价格示例、写入和删除价格示例、Firebase 价格方案:单价和免费用量
- 从 Standard 迁移到 Enterprise、Firestore 版本说明
- Enterprise 入门、管理数据库、数据库设置(REST)、位置、配额和免费用量
- Enterprise 索引、索引 JSON 格式、Query Explain、Query Insights
- Pipeline 安全规则、App Check、Cloud Functions 触发器、模拟器
