PostgreSQL:将在整数列中用完ID

Mat*_*tej 6 java postgresql

问题

我们正在PostgreSQL之上构建一个Java应用程序.它非常大而且成功,它应该能够至少运行几年.

不幸的是,我们(好吧,我)在设计过程的早期阶段犯了一个严重的错误:所有的数据库ID都是整数,从一个共享序列中分发出来.

Java的max int是2 ^ 31-1,所以大约有2亿.这同样适用于PostgreSQL的整数类型.该系统目前每天消耗大约1万个ID,随着新用户的增加,这个速度正在上升.

有一天,ID将耗尽并溢出.

我们正在寻找解决问题的方法.让我们立刻明白这一点:切换到Java long和Postgres bigint是一个干净的解决方案,但这是一项大量的工作.我们需要尽可能地推迟它.

到目前为止我们已经有了一些想法:

  • 不要为一切使用一个序列,给每个表自己的序列.
    • 优点:这给了我们多达N倍的时间,其中N是表的数量.
    • 缺点:我们喜欢每一行都有唯一ID的事实.
  • 停止使用某些表的序列ID.例如,具有客户事件的表实际上不需要ID:customer, timestamp是完全有效的主键.
    • 优点:我们的一些最大的生猪可以通过这种方式改变.
    • 缺点:非常重要的工作量.
  • 停止在空记录上浪费ID.这种情况发生在一些子表中,例如客户联系信息.使记录始终存在使代码更简单,但这意味着许多客户存储了空的联系信息记录.
    • 优点:我们的一些最大的身份证可以通过这种方式修复.
    • 缺点:我们失去了代码简单性.
  • 每个新表必须使用long/ bigint使用新序列.
    • 优点:至少我们不会让情况变得更糟.
    • 缺点:与其余代码的接触面将是丑陋的.

在这些限制下,还有哪些其他方法会延迟ID耗尽?

hru*_*ske 5

切换到 long 远非一个干净的解决方案。如果你变得太大,只有一种明智的选择:UUID(是的,PostgreSQL 带有 uuid 数据类型)。

128 位时,其大小为 4 个整数,但您不想在几年内完成整个应用程序并再次完成所有这些,是吗?当您变得太大并且需要对数据进行分片时,UUID 就会发挥作用。那么你将无法拥有共享序列,这就是 UUID 有意义的原因。

作为奖励,您甚至可以在每一行保留您独特的财产。


迁移并没有那么难:在PostgreSQL中添加一个带有NULL的列很便宜,所以你可以先添加一个列,然后批量进行在线迁移,一次更新几千条记录,这样你就不会停机。

然后您可以使用两个外键测试相同的代码。Java有类似LaboratoryScientist的东西吗?

工作量会很大吗?是的,但这显然是一个好兆头,如果您有一个如此受欢迎的应用程序。

我还希望您已经吸取了对所有表使用相同序列的教训。老实说 - 我真的没有看到其中的附加价值。如果您想知道对象适合的位置,您还可以以不同的方式命名主键(例如 room_id、reservation_id 等)。