如何更改 Postgres 主键列值?

Jak*_*yle 4 postgresql query primary-key

我的 postgres 数据库有一个名为“id”的列,其范围从 40,000,000 到大约 50,000,000。“id”列是主键。我需要更改“id”列值,使它们跨越不同的数字,以便将此数据库与另一个数据库合并。

我如何生成代码以将值从 40,000,000 - 50,000,000 更改为 0 - 10,000,000?

表的定义是

CREATE TABLE public.keyvaluehistory (
   id bigint NOT NULL
      DEFAULT nextval('keyvaluehistory_id_seq'::regclass),
   segkey text NOT NULL,
   dvalue double precision,
   bvalue bytea,
   tstamp timestamp with time zone,
   CONSTRAINT keyvaluehistory_pkey PRIMARY KEY (id)
);
Run Code Online (Sandbox Code Playgroud)

表上没有外键。

我可以承受几分钟/几小时的停机时间。

Lau*_*lbe 5

我会暂时添加另一列。

第一部分可以在数据库处于活动状态时运行:

ALTER TABLE keyvaluehistory ADD new_id bigint;

CREATE SEQUENCE keyvaluehistory_new_id_seq OWNED BY keyvaluehistory.new_id;

/* update in batches to avoid table bloat */

UPDATE keyvaluehistory SET new_id = id - 39999999
   WHERE id BETWEEN 40000000 AND 40999999;

VACUUM keyvaluehistory;

UPDATE keyvaluehistory SET new_id = id - 39999999
   WHERE id BETWEEN 41000000 AND 41999999;

VACUUM keyvaluehistory;

...

SET maintenance_work_mem = '1GB';

CREATE UNIQUE INDEX CONCURRENTLY keyvaluehistory_new_pkey (new_id);
Run Code Online (Sandbox Code Playgroud)

接下来的部分会锁定表并需要停机时间。

最耗时的部分是添加主键,因为这需要扫描表。

/* downtime starts here */

BEGIN;

LOCK TABLE keyvaluehistory IN ACCESS EXCLUSIVE MODE;

/* catch up */

UPDATE keyvaluehistory SET new_id = id - 39999999
   WHERE new_id IS NULL;

ALTER TABLE keyvaluehistory
   DROP CONSTRAINT keyvaluehistory_pkey;

ALTER TABLE keyvaluehistory
   DROP COLUMN id;

ALTER TABLE keyvaluehistory
   ADD CONSTRAINT keyvaluehistory_pkey USING keyvaluehistory_new_pkey;

ALTER INDEX keyvaluehistory_new_pkey RENAME TO keyvaluehistory_pkey;

ALTER TABLE keyvaluehistory RENAME new_id TO id;

ALTER SEQUENCE keyvaluehistory_new_id_seq RENAME TO keyvaluehistory_id_seq;

SELECT setval('keyvaluehistory_new_id_seq', 10000001);

COMMIT;
Run Code Online (Sandbox Code Playgroud)

请在生产环境中运行之前进行测试;我可能忘记了什么。