PostgreSQL:单独的UPSERTINSERT INTO ... ON CONFLICT的效率与合并为单个命令的效率

问题描述

以下多个luigi.build([TaskD(...),TaskB(...)]) 操作中,哪个操作效率更高(等于执行速度更快)?还是没有什么不同?

单独的查询

UPSERT

或将相同的命令组合成一个查询

INSERT INTO mytable (col_1,col_2) VALUES (312,42) ON CONFLICT col_1 DO UPDATE SET col_2=excluded.col_2;
INSERT INTO mytable (col_1,col_2) VALUES (933,32) ON CONFLICT col_1 DO UPDATE SET col_2=excluded.col_2;
...
INSERT INTO mytable (col_1,col_2) VALUES (121,16) ON CONFLICT col_1 DO UPDATE SET col_2=excluded.col_2;

请记住,我正在谈论要执行的{strong>很多命令……要分多批处理(其中很多),每批大约需要750000 INSERT INTO mytable (col_1,col_2) VALUES (312,42) ON CONFLICT col_1 DO UPDATE SET col_2=excluded.col_2 (933,32) ON CONFLICT col_1 DO UPDATE SET col_2=excluded.col_2 ... (121,16) ON CONFLICT col_1 DO UPDATE SET col_2=excluded.col_2; 命令。

解决方法

就像注释中的@a_horse_with_no_name一样,运行单个语句通常比多个语句更有效率。但是,正确的语法是

INSERT INTO mytable (col_1,col_2)
VALUES
    (312,42),(933,32),...
    (121,16)
ON CONFLICT col_1 DO UPDATE
    SET col_2 = excluded.col_2;

请注意,使用参数化查询执行此操作时,参数数量受到限制,因此您可能必须对它们进行批处理。

,

在您的情况下,第一个变体仅是安全的。

在使用ON CONFLICT子句时,在单个查询中插入多个记录是不安全的,如果插入的两行具有相同的冲突键值,则可能会出现致命错误,如"ON CONFLICT can not affect the same row twice."