【问题标题】:PostgreSQL auto-increment increases on each update每次更新时 PostgreSQL 自动增量都会增加
【发布时间】:2016-12-24 06:52:58
【问题描述】:

每次我执行 INSERT 或 UPSERT(ON CONFLICT UPDATE)时,每个表上的增量列都会按之前的更新数递增。

例如,如果我有这张桌子:

id int4
title text
description text
updated_at timestamp
created_at timestamp

然后运行这些查询:

INSERT INTO notifications (title, description) VALUES ('something', 'whatever'); // Generates increments ID=1

UPDATE notifications title='something else' WHERE id = 1; // Repeat this query 20 times with different values.

INSERT INTO notifications (title, description) VALUES ('something more', 'whatever again'); // Generates increments ID=22

这是一个相当大的问题。我们正在运行的脚本每天处理 100,000 多个通知。这可能会在每次插入之间产生大约 10,000 的间隙,因此我们可能从 100 行开始,但当我们达到 1,000 行时,最后一行的自动递增主键 ID 值超过 100000。

如果这种情况继续下去,我们将很快用完表上的自动增量值。

我们的 PostgreSQL 服务器是否配置错误?使用 Postgres 9.5.3。

我正在使用 Eloquent Schema Builder(例如 $table->increments('id'))来创建表,我不知道这是否与它有关。

【问题讨论】:

  • "如果这种情况继续下去,我们将很快用完表上的自动增量值"我对此表示怀疑。如果您每秒 24/7(没有任何停顿)燃烧 10.000 个值,则需要 29.247.120 年才能用完(bigint)值

标签: postgresql


【解决方案1】:

无论插入是否成功,只要尝试插入,序列就会递增。一个简单的update(如您的示例)不会增加它,但insert on conflict update 会因为insertupdate 之前尝试。

一种解决方案是将id 更改为bigint。另一个是不要使用序列并自己管理它。另一个是手动插入:

with s as (
    select id
    from notifications
    where title = 'something'
), i as (
    insert into notifications (title, description)
    select 'something', 'whatever'
    where not exists (select 1 from s)
)
update notifications
set title = 'something else'
where id = (select id from s)

这假设title 是唯一的。

【讨论】:

    【解决方案2】:

    您可以通过在插入命令之前运行此命令将自动增量列重置为最大插入值:

    SELECT setval('notifications_id_seq', MAX(id)) FROM notifications;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 2023-03-29
      • 2019-05-12
      • 1970-01-01
      • 2018-11-04
      • 2015-12-16
      • 2020-08-27
      相关资源
      最近更新 更多