我试图找出最快的方法:
- 如果不存在则插入一行
- 替换(一次所有列)该行(如果存在)
我考虑过DELETE
+ INSERT
,但这看起来像 2 次扫描,如果我执行INSERT
+ ON CONFLICT
,我会得到一个巨大的查询,其中所有内容都必须复制。
有没有公认的方法来做到这一点?
我试图找出最快的方法:
我考虑过DELETE
+ INSERT
,但这看起来像 2 次扫描,如果我执行INSERT
+ ON CONFLICT
,我会得到一个巨大的查询,其中所有内容都必须复制。
有没有公认的方法来做到这一点?
这是UPSERT ( )的一个公认案例。
INSERT ... ON CONFLICT .. DO UPDATE ...
而简单的情况只涉及一次索引扫描。(除了可能的锁定和写入以及索引更新。)
一方面,并发写入负载下的竞争条件通常会更智能地处理。看:
而且它通常也更便宜。“如果存在则替换(一次所有列)该行”听起来有点可疑。如果“该行存在”,则至少一列或多列必须相同。另一方面,
UPDATE
在任何情况下都写入一个新的行版本(如果它完全写入)。如果可以结转烘烤字段或使用 HOT 索引条目,那仍然比DELETE
+便宜。看:INSERT
UPDATE
您的“必须复制所有内容的巨大查询”表明存在优化的潜力或可能的误解。如果可能是这种情况,请显示您的查询以及您的 Postgres 版本、可重现的设置和所需的结果(在一个新问题中!)。
也就是说,如果您没有烤列,没有繁重的并发写入负载,并且索引很少(或只有一个),那么
DELETE
+INSERT
只会稍微贵一些。在没有并发写入负载的情况下替换表的大部分内容时,它甚至可能更便宜。您可能会在和
VACUUM
之间的表格...但这与问题中的用例相去甚远。DELETE
INSERT