在 postgres 中有很多序列有什么问题吗?

use*_*114 4 postgresql sharding primary-key sequence composite-primary-key

我正在使用 postgres 中的虚拟私有数据库模式开发应用程序。

所以每个用户都会得到他的 id,这个用户的所有行都会持有这个 id 以与其他人分开。这个 id 也应该是主键的一部分。此外,每一行都必须有一个在用户范围内唯一的 id。这个 id 将是主键的另一部分。如果我们必须在多个服务器上扩展它,我们还可以将第三列附加到 pk 标识生成此 id 的分片。

我现在的问题是如何为每个用户创建唯一 ID。我提出了一些我不确定所有影响的选项。对我来说最有希望的 2 个解决方案是:

为每个用户创建一个序列:

这可以在每次创建用户时使用触发器自动完成。这肯定是交易安全的,我认为就性能而言应该是可以的。我担心的是,这必须适用于很多用户(100k+),我不知道 postgres 将如何处理 100k+ 序列。我试图找出序列是如何实现的,但没有运气。

用户表中的计数器:

将所有用户保存在一个表中,其中一个字段包含为该用户提供的最新 ID。当用户启动事务时,我可以锁定用户表中的行,并使用用户表中的最新 id 作为起始值创建一个临时序列。然后可以使用此序列为新条目提供 ID。在退出事务之前,必须将当前值写回用户表并释放锁。如果来自同一用户的另一个事务尝试并发插入行,它将停止,直到第一个事务释放其对用户表的锁。这样我不需要成千上万的序列,我不需要

我的问题的第二部分是我是否应该只使用 2 列(或者如果 shard_id 加入游戏,则可能是三列)并使它们成为复合 pk 或者我是否应该将它们放在一列中。我认为将它们放在单独的列中会更容易处理,但性能如何?让我们假设两个值都是 32 位整数 - 在索引中包含 2 个 int 列还是在 1 个 bigint 列中更好?

感谢所有答案,亚历克斯

har*_*mic 5

我不认为序列可以扩展到您想要的级别(100k 序列)。序列被实现为只有一行的关系。

每个序列都将出现在系统目录 ( pg_class ) 中,该目录还包含所有表、视图等。有 100k 行肯定会显着降低系统速度。保存与这些序列关系相关联的所有数据结构所需的内存量也会很大。

你的第二个想法可能更实用,如果结合临时序列,可能更具可扩展性。

对于您的第二个问题,我认为复合键不会比单列键差,所以我会选择符合您功能需求的任何东西。