PostgreSQL自动增量每次更新都会增加

时间:2016-08-17 14:35:09

标签: postgresql

每次执行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行时,我们在最后一行有一个超过100000的自动递增的主键ID值。

如果继续,我们将快速耗尽我们的表上的自动增量值。

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

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

2 个答案:

答案 0 :(得分:5)

无论成功与否,只要尝试插入,序列就会递增。一个简单的update(如您的示例中所示)将不会增加它,但insert on conflict update将会insert,因为update会在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) 。另一个不是使用序列并自己管理它。另一个是做手动upsert:

title

这假设int main() { boost::mt19937 uGenOne(1); boost::mt19937 uGenTwo(1); uGenTwo.discard(1); unsigned int M = 10; std::vector<double> variatesOne(M); std::vector<double> variatesTwo(M); for (unsigned int m = 0; m < M; ++m) { variatesOne[m] = uGenOne(); variatesTwo[m] = uGenTwo(); } for (unsigned int m = 0; m < M; ++m) std::cout << std::left << std::setw(15) << variatesOne[m] << variatesTwo[m] << std::endl; return 0; } 是唯一的。

答案 1 :(得分:0)

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

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