我为什么放弃 Google Firestore

2025-05-27

我为什么放弃 Google Firestore

由engine.so提供- 这是一种使用 Notion 为您的客户即时创建公共自助知识库的工具。

Google Firestore 是 Google 专有的 NoSQL 文档型数据库。它与 Firebase 套件的其他功能(例如 Cloud Functions、Firebase Auth 和 Firebase Storage)搭配使用,对于希望快速上线应用的初创公司或个人开发者来说,是一个极具吸引力的技术栈。
这正是我 9 个月前为我的移动应用选择技术栈时的想法。Firestore 有一些吸引我的优势。它拥有慷慨的免费套餐、自动扩展的 NoSQL 数据模型,以及与其他 Firebase 服务的完美集成。如果你现在觉得自己正沉浸在这项技术的美好幻想中,这里有一个建议……
务必了解 Firestore 的缺点。


我不再使用 Firestore 的三大原因

1.专有数据库

我们都听说过“供应商锁定”这个词。Firestore 就是这个概念的典型代表。如果你觉得你的产品简单或规模小,这不会成为问题,那么我现在就告诉你,即使是最简单的应用程序,Firestore 的供应商锁定也会悄然出现。我在尝试部署数据库的 DEV 和 PROD 版本这个简单任务时就遇到了这个问题。这对 Firestore 来说是一个巨大的挑战。

您遇到的第一个障碍是,您无法将多个 Firestore 数据库与一个项目关联。因此,您必须创建单独的 project-dev 和 project-prod 项目。这最初并不难,而且通常来说可能是一种不错的设计模式,但现在您的开发体验会变得复杂两倍。现在,您必须决定是否要为每个项目分配单独的 Firebase Auth,以及云函数、存储桶等。而且,没有任何工具可以自动化任何此类部署,因此,如果您只想将数据库数据和函数以及用户身份验证“复制”到生产环境,则必须手动完成。即便如此,其中一些操作可以通过 Firebase CLI 完成,但更重要的操作(例如迁移数据)则无法完成。

假设你已经搭建好了生产和开发环境,现在你又会遇到另外 20 个问题。如何进行自动备份?如何自动将数据从一个数据库导出到另一个数据库以刷新暂存服务器?如何让这个数据库的本地版本运行起来进行测试?所有这些问题的答案是……它很复杂。这些更复杂的用例很难实现,因为这个数据库不是开源的,所以没有社区为这些事情开发工具。

有些问题并非 Firestore 独有,而是所有专有数据库供应商都会遇到的。这就是为什么我再也不会选择专有数据库了。当然,尝试最新最好的产品也是一种习惯,但当涉及到公司最重要的资产(数据)的完整性、安全性和可访问性时,我十有八九会说,使用经过开源测试的解决方案是更好的选择。


2. Firestore 只为自己优化,不为你优化。

在使用 Firestore 时,这部分确实让我很恼火。事实上,Firestore 有两个功能总是互相矛盾。

  1. 当您读取/写入数据库时​​,Firestore 按文档收费。

  2. Firestore 的查询能力非常原始,因此更复杂的数据过滤、排序或合并必须在客户端完成。

这种致命的组合意味着,如果您必须执行更复杂的查询(这几乎是不可避免的),您将需要过度获取数据,然后在使用之前在云函数或客户端进行过滤。这不仅浪费了网络带宽和客户端处理时间,而且由于 Firestore 的支付策略,最终还会花费您更多的钱。我所看到的最大后果是

结果是,我的数据库集合和可用的查询操作定义了我在产品中实现的功能,而不是由我的客户来决定。

现在我要稍微扮演一下魔鬼代言人的角色,因为我明白 Firestore 为什么要这样设置。因为 Firestore 的设计初衷只有一个:让你很难写出糟糕的查询。几乎所有你能在 Firestore 中执行的查询都是 O(1) 复杂度的。这很棒,因为这意味着你的数据库处理时间很短,客户端可以很快得到结果。但是……

你明白了吗?

Firestore 的设计初衷是降低服务器端的处理成本。但你猜怎么着?你按文档付费,所以查询耗时 1 毫秒还是 100 毫秒,对你来说都无关紧要。这意味着 Firestore 正在优化,以降低他们的成本,而不是你的成本。而且,由于你必须在客户端过度获取数据并手动过滤,最终会导致查询成本更高、速度更慢。这就是我放弃 Firestore 的原因。在了解了他们的商业模式后,我明白了,我根本不想用这个产品来扩展规模。


3. NoSQL 数据库可能不适合你

Firestore 最初吸引我的一点是它的 NoSQL 数据模型。NoSQL 还有其他选择,例如 MongoDB 或 AWS DynamoDB,但 Firestore 为我提供了一个非常好的开箱即用的自动扩展解决方案,我立刻就喜欢上了它。直到后来我不再喜欢它了。

您会发现,典型的 Web 或移动应用程序的大多数数据都具有高度关系性。典型的应用程序可能包含用户,以及与用户以某种方式相关的事物。而这些事物也可能与其他事物相关,等等。这些数据可能会以列表形式显示,或被索引,或被查询以查看用户创建的所有事物。对于管理这些基本用例,Firestore 还算可以,但一旦情况变得更加复杂,Firestore 就会失效。

NoSQL 针对这些问题的解决方案包括数据重复、扇出式写入等。这些原则的实现比一开始就拥有 SQL 数据库需要更多的开发时间。如果您正在考虑使用 Firestore 作为解决方案,您可能希望节省开发时间,因为这是 Firebase 的卖点,但 Firestore 更像是承担了一笔以后必须偿还的时间债务。为了说明我在开发过程中遇到的一些非常棘手的障碍,我将从我的项目中举几个简单的例子:

  • 用户可以创建评论。用户的头像和用户名会附加到他们创建的每条评论中。这是必需的,因为前端会查看评论列表。如果我们必须获取所有评论,然后对每条评论进行第二次查询以获取用户头像和用户名,那么这 1 次查询就变成了 N+1 次查询。这被称为 N+1 问题。然后,用户更改了姓名。现在,您必须编写一个云函数来感知该更改,并动态搜索每份报告(可能有数百万份),并在每份包含该用户旧姓名的报告中更改其显示名称。对于 SQL 数据库中开箱即用的功能而言,这需要大量的编程工作。

  • 用户注册时需要选择用户名。我想确保两个用户的用户名不同(忽略大小写)。用 Firestore NoSQL 解决这个问题的方案是什么?我不得不为每个用户添加一个 lowercaseUsername 字段。当用户想要更改用户名时,它会将其转换为小写,然后查询该字段是否已存在,如果不存在,则更改用户名。如果您的应用已经投入生产,这将非常痛苦,因为回填每个用户文档以添加 lowercaseUsername 字段需要开发时间来编写一次性函数来执行此迁移。我发现我不得不一直回填数据,最终变得难以处理。

  • 用户可以关注 Trails。Trails 可以有多个用户关注。这在这些对象之间建立了多对多关系。在 Firestore 中管理这些关系非常繁琐。当你只需要考虑创建数据时,这还算简单,但之后你还必须处理更新和删除数据,这会带来极大的复杂性。

正如你所见,NoSQL 数据库在很多情况下会给你带来麻烦,并浪费大量的开发时间。SQL 数据库现在非常可扩展且功能强大,能够更好地满足你的需求。猜猜怎么着?如果你想要两全其美,可以同时使用两者。将关系数据库放入 SQL 数据库,将非关系数据(例如数百万条实时聊天消息)放入 NoSQL 数据库,这样就可以兼得两者的优势,而无需权衡任何一方的利弊。


Firestore 适合您吗?

我仍然喜欢 Firestore 的几个方面。他们管理客户端离线支持的客户端 SDK 非常方便,而且对于查询非关系型的简单数据,我仍然会考虑使用它。但除非我知道我的项目有固定的完成日期,并且不会遇到上述任何限制,否则我不会推荐它。


那么 Firestore 的替代品是什么?

如果您和我一样,喜欢从数据库获取嵌套的 JSON 响应,那么您应该考虑使用 GraphQL。我切换到 GraphQL 并搭配 SQL 数据库使用,发现它达到了完美的平衡,既保留了之前喜欢的所有便捷查询功能,又能直接查询数据库,方便我处理更复杂的事务。我还发现速度仍然相当,而且如果数据库在扩展过程中速度变慢,我可以添加只读副本。

对于其他用例,我的建议如下:

如果您想要一个简单的存储桶来存放数据,那么可以考虑查看类似 Contentful 的东西:https://www.contentful.com/

如果您想要一个易于使用的开源 UI,以便在开源 Postgres 数据库之上制作 CRUD API,请考虑使用 Hasura + Postgres 的 GraphQL:https://hasura.io/

如果您想要一个不需要处理数据重复的 SQL 数据库,但又不想使用 GraphQL 或管理数据库扩展,请考虑使用 AWS Aurora:
https://aws.amazon.com/rds/aurora/

替代文本

查看我:https://spencerpauly.com

文章来源:https://dev.to/spencerpauly/why-i-switched-away-from-google-firestore-3pn
PREV
身份验证:Cookie 与 Token
NEXT
大家好,我是 Christine,我从 15 岁起就开始为 Debian 做贡献。现在我是 Nylas 的 CTO,有什么问题可以问我!