就直接上 Postgres 吧

/ Ethan McCue

省流:绝大多数情况下,你都应该无脑选择 Postgres 作为你的数据库后端。

本文是 Just use Postgres 的转译,文章内容因个人恶趣味与原文可能有所出入。如需引用请以原文为准。


这篇文章一方面是给出一些可执行的建议,另一方面是希望读者可以审视自己对于数据库的选择。

建议:当你构建一个需要使用持久存储的程序的时候,比如说构建一个 Web 应用的时候,你应该默认选择 Postgres.

为什么不用 sqlite?

sqlite 是很好的数据库,但是它是运行在单文件之上的。

这就意味着你的程序要么只能运行在一台机器上,要么只能通过共享文件系统的方法来实现多机运行。

如果你在设计一个桌面端或者移动端应用这种单机应用的话,用 sqlite 当然再合适不过。但如果你在设计一个 Web 应用的话就未必了。

当然,使用 sqlite 设计 Web 应用也有很多成功案例,但是这些案例基本上都需要你自行架设服务器和管理基础设施。PaaS 提供商,比如 Heroku, Railway, Render 等等,通常会假定你会通过网络访问数据库。当然抛弃这些平台提供的能力称不上是「错」,不过你可能想考虑一下用 sqlite 和数据库自动备份、部署多个程序的能力之间哪个更符合你的需要。

官方文档中有关于「何时该使用 SQLite」这个问题的更详细的说明。

为什么不用 DynamoDB, Cassandra 或者 MongoDB?

无论 Rick Houlihan 现在在哪,我都祝他过着幸福美满的生活。

我听过很多的讲座。其中我反复听的最多的还是他的 2018 DynamoDB 深入解析。我知道大多数人不会想去听一个多小时的讲座,但你真的应该听一下,讲得非常好。

DynamoDB 和其同类数据库,包括 CassandraMongoDB, 几乎完美无缺,但前提是,而且这个是决定生死的大前提:

这是因为这类数据库从原理上而言就是一个大型分布式哈希表。除了按分区键查找值和按排序键扫描以外,其他一切操作都得扫描整个数据库。

无论你想要执行哪种查询,你都得把关于这个查询的相关知识编入到索引当中。比如,你想要存储用户的姓名,之后可以按姓或者名来查找?那你最好就设计好形如 <姓>$<名> 的排序键。你的访问范式需要被刻画进你的数据存储方式里。一旦你的访问范式发生了变化,你甚至可能需要重新编译所有的数据。

这点十分痛苦,尤其是 MongoDB 还不遗余力地宣传所谓的「灵活数据库」。是,你确实不用提前给数据库制定好表结构;是,你可以直接把无类型的 JSON 文档干到集合里;但不,这些数据库不是什么灵活数据库,而是高效数据库。

关系型数据库可以让你从「某人的所有宠物」轻松变换到「某宠物的各任主人」,如果要考虑性能的话就额外再添加一两个索引就行。但对于非关系型数据库而言,这个变换实现起来就比较棘手了。

而且非关系型数据库也很难处理分析式查询。分析式查询就是诸如「上个月新注册多少用户」这样的问题。这些问题用 SQL 就很好回答,就算你担心性能问题也可以在一个只读副本上运行查询,这样就不会影响到生产端。对于 NoSQL 类数据库你就没这个好运了:你得自己把数据全部提取过滤一遍才能得到结果。

如果你发现一个本科生或者研一的打算用 MongoDB, 阻止他,别让他走上歧路。

为什么不用 Valkey?

曾用名为 Redis, 它的最佳用例是用作进程外缓存。你可以只做一次费时费力的计算然后把结果丢给 Valkey, 这样之后的 5 次或者随便几次的 HTTP 请求就不需要再重新做计算了。

不过,你还是可以把它用作主要数据库的。它的所有数据都保存在 RAM 里,所以操作起来相当快。

当然,这么做会有一些明显的问题:

为什么不用 Datomic?

如果你已经知道 Datomic 是什么的话,给你发一颗小星星。

Datomic 是一个 NoSQL 数据库,但是它是关系型的。所以「提前设计好」的问题就不存在了,而且它还有许多非常有意思的性质。

你不需要把数据存在表里面。它使用的是实体-属性-值-时间四元组。你不需要设计一个 person 表存放 id, nameage, 你只需要存储 1 :person/name "Beth" 然后 1 :person/age 30. 然后你的查询就全部基于一种「通用」索引进行。

你不需要和其他写入端协调写入顺序,因为当你查询数据库的时候,你查询的是数据库在某个时间点上的状态。新数据,甚至是数据删除(或者更贴切地说是「回撤」),都不会改动旧数据。

当然,这个数据库也有它的痛点:

为什么不用 XTDB?

Clojure 的人都老爱写数据库了。

XTDBDatomic 一脉相承,不过:

它最大的问题是:

好吧,它确实只有这一个问题。给我点时间我肯定能点出更多问题,不过这个条目主要是当作一个例子来代表所有最近开发出来的数据库。预测一个事物会不会继续存在的最好方法就是看它是不是已经存在了很长时间。COBOL 已经存在了几十年,那它大概率会继续存在几十年。

如果你在考虑使用持久存储,那你肯定会希望这个东西的支持越长越好。你当然可以选一个很新的实验性数据库给你的程序后端用,但即使按下技术上的问题不表,它在运维上也天生带着巨大的风险。所有新的东西都不应该是你的默认之选。

为什么不用 Kafka?

Kafka 是只追加型日志系统。它能处理上 TB 级的数据,是很优异的只追加型日志系统。如果你需要统筹多个团队开发的各种事件源和数据源,用上它是再合适不过了。

但是:

为什么不用 ElasticSearch?

搜索是你的程序的主要功能么?

如果你回答「是」,那么 ElasticSearch 确实能够带来非常显著的提升。当然了,你得自行提取、清洗和加载你的数据而且要自行管理整个流程,但 ElasticSearch 毕竟是为了搜索而生的。搜索这块它做得确实很好。

如果你回答「否」,那么用 Postgres 也无伤大雅。上点 ilike 操作配合它内建的全文搜索能力对于绝大多数应用来说已经足够了。而且之后如果有必要的话,你也可以随时添加专门的搜索功能。

为什么不用 MSSQL 或者 Oracle DB?

我希望你能问问自己:这价格真值得么?

我说的不仅仅是你购买数据库软件的价格,还有和企业绑定的价格。一旦你选择了 Oracle DB, 那么你这辈子就都得给 Oracle 上贡了。你得给每一代员工都培训怎么使用 Oracle DB. 而且你还得不断地在你的钱包和企业功能之间做抉择。

我也知道你估计也不会给 Postgres 贡献代码,所以我也不提什么「开源,好」之类的东西。但我认为你在选择一个私有数据库之前还是有必要考虑一下这茬。如果你不是因为看中了 MSSQL 里面某个独有的功能而且你非用不可,最好不要动这玩意。

为什么不用 MySQL (或者 MariaDB)?

这部分我确实需要大伙来评一下。

MySQL 被 Oracle 收购了,而且它有一些功能是锁在企业版里的。这也意味着你也会面临上面的企业绑定问题。

但是社区版 MySQL 使用得还是非常广的,而且它已经经历过时间的考验,有许多人熟悉怎么使用 MySQL 了。

我的问题是我只花了大约 6 个月的时间来专业地使用 MySQL. 相比于 Postgres, 我确实对它了解得不够多。

我确信它并没有特别优秀之处,至少我建议大家转用 Postgres 相比于 MySQL 而言不是什么坏事。而且我之前也读到过 Postgres 对于数据库的完整性和一致性检查的支持要更好。不过我还是很愿意听听大家的看法的。

编者按:评论区中有人指出 MySQL 有一个恶性 Bug 一直拖到今天都没修。这个 Bug 的标题是:触发器在外键更新或删除时没有被执行。考虑到这个 Bug 已经存在了这么长时间,它可能已经成为一种功能了。所以这里的这个「今天」没有标日期——我估计它永远都不会被修好了。

那 AI 向量数据库呢?

为什么不用 Google Sheets / 多维表格?

确实。这个我实在想不出什么缺点,直接上吧。

正在加载评论……

发表评论

您的评论将由管理员审核后方可公开显示。

Your comments will be submitted to a human moderator and will only be shown publicly after approval.