Postgresql:主键的UUID还是SEQUENCE?

Jus*_*Leo 15 mysql postgresql

我来自MySQL,在MySQL中,您可以使用AUTOINCREMENT将行的唯一ID作为主键.

我发现Postgresql中没有AUTOINCREMENT,只有SEQUENCE或UUID.I已经读过我们可以使用UUID作为表的主键的地方.这具有掩盖其他用户id的附加优点(因为我想构建将ID作为参数的API).我应该将哪个用于Postgresql?

Pat*_*ick 25

sequencePostgreSQL中的A 与AUTOINCREMENTMySQL 完全相同.A sequence比a更有效,uuid因为它是8字节而不是16字节uuid.您可以将a uuid用作主键,就像大多数其他数据类型一样.

但是,我没有看到这与屏蔽用户ID有何关系.如果要从其他用户屏蔽某个用户的ID,则应该使用 - 例如 - 仔细管理表权限和/或加密ID md5().

如果你想保护一个包含用户数据的表,而不是来自试图猜测其他ID的窥探黑客,那么该uuid类型是一个很好的选择.版本4是最佳选择,因为它有122个随机位(其他6个用于识别版本).您可以像这样创建一个主键:

id uuid PRIMARY KEY DEFAULT uuid_generate_v4()
Run Code Online (Sandbox Code Playgroud)

然后你再也不用担心了.

  • @Justin:我会同时使用两者.将主键定义为`serial`,并包含一个用于API调用的唯一`uuid`列. (4认同)
  • 我不想掩盖该用户的 ID,只是不想让用户“猜测”其他用户的 ID(例如,该用户的 ID 是 154 而我正在执行 API 请求,可以猜测还有其他用户 ID 153 或 155 并窥探不需要访问令牌的 GET 请求) (3认同)
  • 我不确定效率的提高是否值得使用主键和备用键的复杂性,尽管任何旨在模糊对未知/未经授权数据的潜在访问模式的目的都是好的。如果密钥空间以可预测的(例如顺序)方式消耗,任何依赖于人们无法猜测密钥的系统本质上都是不安全的。 (3认同)
  • 新版本是 `gen_random_uuid () → uuid`。来自官方文档 https://www.postgresql.org/docs/current/functions-uuid.html (3认同)
  • 我同意@holdenweb。如果您要为 UUID 支付索引成本,那么您不妨将其作为您的 PK。旁注,您可能需要考虑使用 [ULID](https://github.com/ulid/spec) 而不是任何符合 RFC 4122 的 UUID,因为 ULID 可以按字典顺序排序,而 UUID 则不能。这种排序具有显着的索引优势,因为新的 id 总是添加到索引的“末尾”而不是随机添加。 (2认同)

小智 16

多年来,我使用 PK 和 FK 作为数字序列值开发了数据库应用程序。这非常有效,但近年来在创建云应用程序时,在应用程序之间交换信息,我们将在我们开发的各种应用程序之间进行集成,我们意识到在我们的 API 中使用顺序 ID 最终会产生一种努力。

在某些应用程序中,我们必须找到要通过 API 调用发送的(目标应用程序的)ID,另一方面,我们的数据库表,在我们所有的应用程序中,除了顺序 PK / FK 列之外,还有一个 UUID 列,未在 API 调用中使用。在这种情况下,我们决定重写 API,以便使用 UUID 列。

这解决了一些问题,因为我们的一个桌面应用程序会将它们的数据迁移到另一个云应用程序,这个云应用程序也使用了 PK / FK 列。在迁移此数据时,我们必须更改新序列的 PK/FK 值,因为这些序列可能会在桌面应用程序的值和云应用程序的值之间发生冲突。考虑到这一点,我们选择将云应用程序 PK/FK 切换到 UUID,因为来自桌面应用程序的数据有一个 UUID 列。

然后的问题是通过将 INT 列(PK 和 FK)转换为 UUID 列来转换云应用程序表,而不会丢失表信息。这是一项艰巨的任务,但它变得更容易了,因为我最终构建了一个应用程序,使这种更改更容易。应用程序将每个 PK / FK 整数列更改为 UUID,保留数据和关系。有兴趣的可以点击链接:

https://claytonbonelli.github.io/int_pk2uuid_pk/

  • 现有的序列 ID 也可以通过使用可预测的 uuid 生成器转换为 uuid,例如“update x set uuid = uuid_generate_v5(uuid_ns_url(), 'some-namespace/' || id)”。因此,可以为每个表添加 uuid 列,独立地用值填充它们,而无需在内存中进行查找/映射,从而使事情变得更快。 (10认同)

All*_*leo 8

其他答案提到了 UUID 的性能问题,但没有太多细节或参考(引用:“它们不是很快”)。

我发现一项综合测试测量 UUID 连接比 int8 慢约 5%,索引大小高约 40%(不是两倍,正如人们从其他答案中可以预期的那样,因为索引大小与所有索引的大小不同)元素)。


Rah*_*thi 6

您可以将UUID用作表中的主键,因为它是唯一的。但是请记住,与SEQUENCE相比,UUID将占用更多空间。而且它们也不是很快。但是,是的,它们肯定是唯一的,因此可以保证您获得一致的数据。

您还可以参考:

  • 你能量化一下“不是很快”的说法吗?当然,生成 uuid 比增加 id 需要更长的时间,但是时间差异是否足以引起合理的关注? (5认同)