PostgreSQL:整数列

时间:2016-02-26 14:58:28

标签: java postgresql

问题

我们正在PostgreSQL之上构建一个Java应用程序。它非常庞大且成功,至少应该可以运行几年。

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

Java's max int is 2^31-1,大约有20亿。 PostgreSQL's integer type也是如此。该系统目前每天消耗大约1万个ID,随着新用户的增加,这个速度正在上升。

有一天,ID会用完并溢出。

问题

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

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

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

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

2 个答案:

答案 0 :(得分:3)

切换到long远不是一个干净的解决方案。如果你变得太大,那么只有一个合理的选择:UUIDs(yes, PostgreSQL comes with uuid data type)。

128位,大小为4个整数,但是你不想在几年内完成整个应用程序,再到这一切,你呢?当你变得太大而你需要对数据进行分片时,UUID会起作用。那时你不可能拥有共享序列,这就是为什么UUID有意义。

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

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

然后,您可以使用两个外键测试相同的代码。 Java是否与laboratoryscientist类似?

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

我也希望你在所有表格中使用相同的序列学到了一课。老实说 - 我真的没有看到附加价值。如果您想知道对象的位置,您也可以不同地命名主键(例如room_id,reservation_id等)。

答案 1 :(得分:1)

自从提出这个问题以来,我找到了解决问题一半的好方法 - 数据库方面。因此,对于后代,这是实现目标的方法。

  1. 查找integerinteger[]类型的所有数据库列。手动检查结果并删除类型列,例如text[]

    SELECT *
    FROM information_schema.columns cls
    JOIN information_schema.tables tbl ON cls.table_name = tbl.table_name
    WHERE
      cls.table_schema = '<my schema>'
      AND cls.data_type = 'integer' OR cls.data_type = 'ARRAY'
      AND tbl.table_type = 'BASE TABLE';
    
  2. 为每个列准备数据类型更改DDL:

    ALTER TABLE <one of the tables found> 
    ALTER COLUMN <one of its integral columns> 
    TYPE bigint;
    
  3. 除了VIEW之外,它的效果非常好:他们不喜欢我改变他们的回归类型。我需要重新创建所有这些 - 序列将是

    1. 删除所有观看次数。
    2. 更改列类型。
    3. 重新创建所有观点。
  4. 停止应用程序,从步骤3运行升级脚本,通过在所有表上运行VACUUMANALYZE来修复慢速查询。
  5. 在源代码中运行测试并修复问题 - 例如,bigint[]无法转换为integer[]
  6. How to export/backup VIEWs only?