Lætitia AVROT:PGSQL Phriday #015:主键选择:UUID、CUID 还是 TSID?

💡 原文英文,约800词,阅读约需3分钟。
📝

内容提要

这篇文章讨论了在使用Postgres时,是否应该使用UUID、CUID或TSID作为主键。作者认为,在Postgres中使用UUID、CUID或TSID没有有效的理由。此外,作者还提到,在大多数情况下,不需要对Postgres进行水平扩展,因为它本身性能良好。作者建议在优化关系型数据库时,首要原则是“仔细设计数据模型”。

🔎

延伸解读

主键生成:数据库职责与性能考量

作者强调主键应由数据库生成,而非应用程序。在Postgres中,使用“generated always as identity”列可确保ID顺序生成,利用B-tree索引对顺序数据的优化,减少WAL日志量。而UUID、CUID等随机ID会破坏顺序性,导致索引效率下降和WAL增加,除非工作负载是随机更新而非顺序插入。

UUID的常见理由在Postgres中为何不成立

文章反驳了使用UUID的两个常见理由:一是避免中心化系统,但Postgres本身就是中心化系统;二是防止用户猜测ID,但作者认为这本质是访问控制问题,应通过权限检查解决,而非依赖ID的不可猜测性。因此,在Postgres中这些理由并不成立。

水平扩展:大多数场景并非必要

针对“需要水平扩展”的疑问,作者指出Postgres原生不支持水平扩展,且在其经验中,超过90%的用例并不需要扩展,因为Postgres性能足够好,只要正确维护即可。因此,不应以扩展为由选择UUID等主键。

优化首要原则:精心设计数据模型

作者提出优化关系型数据库的“第0条规则”是“仔细设计数据模型”。这意味着在考虑主键类型等优化前,应先确保数据模型合理。使用自动生成的身份列并在自然主键上添加唯一约束,是简单且可靠的做法,避免因不了解深层影响而引入问题。

❓

Q&A

在Postgres中,主键应该由数据库生成还是应用程序生成?

作者认为数据库应该负责生成主键,而不是让应用程序创建主键。建议使用“自动生成的身份列”(generated always as identity column),并在自然主键上添加唯一约束。

为什么在Postgres中使用UUID作为主键可能影响性能?

因为Postgres使用B-tree索引来强制唯一性,而B-tree索引在数据是顺序时效率更高。UUID是随机的,会破坏顺序性,导致WAL生成量远高于顺序ID。

UUID、CUID和TSID分别是什么?

UUID是128位的唯一标识符;CUID旨在提供比UUID更强的唯一性保证,并防止泄露信息;TSID是时间排序的唯一标识符。

在Postgres中,是否有必要使用UUID、CUID或TSID作为主键?

作者认为没有有效理由。Postgres本身是中心化系统,应用程序生成ID的理由不成立;随机ID用于UI安全是错误的安全观念,应通过权限控制解决。

Postgres在大多数情况下需要水平扩展吗?

作者认为不需要。根据经验,超过90%的用例不需要水平扩展,因为Postgres性能足够好,只要正确维护就能表现良好。

优化关系型数据库的首要原则是什么?

作者提出规则0是“仔细设计数据模型”。此外,优化的一般规则是:如果不是专家,不要优化;即使是专家,也不要急于优化。

🏷️

标签

➡️

继续阅读