PostgreSQL Upsert更新记录时为何递增序列last_value?
关于PostgreSQL Upsert导致bigserial序列断层的疑问
我有一个PostgreSQL表,主键id为bigserial类型,目前序列值已达数百万,但表中实际仅有数百条记录。该表频繁执行以下Upsert语句:
INSERT INTO test_table (ticker,column1) VALUES ('a','1') ON CONFLICT (ticker) DO UPDATE SET column1=EXCLUDED.column1;
测试后发现:当ticker已存在(触发更新操作)时,序列仍会递增;只有插入新记录时,Upsert才会将序列last_value+1作为id值。
为验证该行为,我创建了测试表:
CREATE TABLE public.test_table ( id bigserial NOT NULL, ticker varchar(10) NOT NULL, column1 varchar(10) NULL, CONSTRAINT test_table_pk PRIMARY KEY (id), CONSTRAINT test_table_unique UNIQUE (ticker) );
自动生成的序列test_table_id_seq初始last_value为1。执行首次Upsert插入新记录后,last_value仍为1,id为1,符合预期。
随后执行3次触发更新操作的Upsert语句后,序列last_value增至4,但表中最高id仍为1。再插入新记录时id变为5,出现了序列断层。
目前我只能通过每次Upsert后执行以下语句重置序列来避免断层:
SELECT setval('test_table_id_seq', (SELECT MAX(id) FROM test_table));
请问该行为是否正常?我是否遗漏了什么关键点?
内容的提问来源于stack exchange,提问作者jr-scalawag
相关产品推荐
相关产品推荐

