Postgres:在批量插入期间忽略错误的最佳解决方案

时间:2015-12-28 07:08:00

标签: sql postgresql

我在这里看过很多类似的问题。但我的问题,我猜,具体。

这是我在Postgres的当前版本(9.4)中找到的最佳解决方案: http://www.depesz.com/2012/06/10/why-is-upsert-so-complicated/ http://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-UPSERT-EXAMPLE

通常,建议的解决方案基于算法:插入一行,如果发生错误 - 执行某些操作,如果没有 - 插入下一个。

如果我只需要忽略重复错误,我可以这样做吗?

INSERT INTO tablename (id,name,surname) values (1,'john','doe')
INSERT INTO tablename (id,name,surname) values (2,'jane','smith')

而不是:

INSERT INTO tablename (id,name,surname) values (1,'john','doe'),(2,'jane','smith')

...如果我必须一次只插入约5-30行? 因此,一些插入的行只返回重复的错误,但其余的将成功执行。实际上,这就是我所需要的一切。

我试图将这些方法的成本一次与EXPLAIN INSERT 100行和100行分别进行比较。也许,我做错了,因为当我插入行单独时,它显示的执行时间缩短了约25-50倍,如第一个例子所示:

INSERT INTO tablename (id,name,surname) values (1,'john','doe')
INSERT INTO tablename (id,name,surname) values (2,'jane','smith')

这是我正在使用的查询包装器:

BEGIN;
EXPLAIN ANALYZE
-- query or queriES here
ROLLBACK;

所以,问题是,为什么我收到这个?可能是,EXPLAIN显示每行而不是整个查询的执行时间?然后它是有道理的:在这种情况下,批量插入将比分离的命令小约3倍。正确?

1 个答案:

答案 0 :(得分:1)

with i (id, name, surname) as (values (1,'john','doe'),(2,'jane','smith'))
insert into t (id, name, surname)
select id, name, surname
from i
where not exists (
   select 1
   from t
   where id = i.id and name = i.name and surname = i.surname
)

如果可以以任何其他方式插入数据,则存在上述竞争条件。如果发生错误,请重试。