Postgresql:单独的 UPSERT(INSERT INTO ... ON CONFLICT)的效率与组合成单个命令的效率

Postgresql: efficiency of separate UPSERTs (INSERT INTO ... ON CONFLICT) vs combining into single command

以下哪个 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;

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

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;

请记住,我说的是要完成 很多 INSERT 命令...分批(很多)每批大约 750000 INSERT 个命令。

在你的情况下,第一个变体是唯一安全的。

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

正如评论中@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;

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