在 postgres 中更新具有大量删除的表的主键序列

Posted

技术标签:

【中文标题】在 postgres 中更新具有大量删除的表的主键序列【英文标题】:Updating sequence for primary key in postgres for a table with a lot of deletions 【发布时间】:2020-09-17 23:35:04 【问题描述】:

我有以下问题:我有一个包含大量删除和插入行的表。此外,我想为表中的每个当前行分配一些 id 号。目前我正在尝试使用

DROP SEQUENCE IF EXISTS market_orders_seq
CREATE SEQUENCE market_orders_seq CACHE 1
CREATE TABLE market_orders (id int NOT NULL DEFAULT nextval('market_orders_seq') PRIMARY KEY, typ varchar(5), tag varchar(30), owner_id int, owner_tag varchar(5), amount int, price int, market_id int)
ALTER SEQUENCE market_orders_seq OWNED BY market_orders.id

但是如果我理解正确的话,序列是单调的,当我删除一些行时不能下降,所以我遇到了一个 id 被快速膨胀的问题。这个问题的解决方案是什么?我想将第一个未使用的 id 用于插入,但我不知道该怎么做。

【问题讨论】:

【参考方案1】:

虽然这在技术上是可行的,但我实际上并不建议这样做。

首先,一个整数值可以存储高达 2 大约十亿的值,你可能不会遇到 - 你仍然可以切换到 bigint,它可能会达到大约 1^19

此外,识别间隙需要为每个插入扫描表,这是低效的(表越大,效率越低)。

insert into market_orders(id, typ, ...)
select
    min(id) + 1,
    'foo',
    ...
from market_orders mo
where not exists(select 1 from market_orders mo1 where mo1.id = mo + 1)

旁注:你应该使用the [big]serial datatype,所以你不需要自己处理序列。

【讨论】:

以上是关于在 postgres 中更新具有大量删除的表的主键序列的主要内容,如果未能解决你的问题,请参考以下文章

如何更新一个主键是另一个表的主键的表?

关于oracle中 根据一个表的主键数据同步更新另一个关联表的字段。

如何在 MySQL 中获取特定表的主键“列名”

获取列名包含大写字符的表的主键时,Jooq 的值无效

oracle修改主键

Oracle修改一个已经存有数据的表的主键