对于同一操作,这两种形式之间的批量更新通常哪个更有效?
选项1:
UPDATE table SET a = val.b FROM (VALUES (0,1), (2,3)) AS val(b,id) WHERE table.id = val.id
选项 2:
UPDATE table SET a = 0 WHERE table.id = 1;
UPDATE table SET a = 2 WHERE table.id = 3;
我在文档中找到了这个:
当出现 FROM 子句时,实质上发生的情况是目标表连接到 from_item 列表中提到的表,连接的每个输出行代表目标表的更新操作。
这是否意味着这两个选项在引擎盖下是等效的?
对于选项 1,我想知道 Postgres 是否只会在最后更新一次索引,在所有行都更新之后,或者每行更新一次。前者应该比后者更有效,这将使选项 1 比选项 2 更好。
仅仅将索引维护延迟到最后不太可能提高效率——这需要更改算法,而不仅仅是延迟。同样的工作仍然要做。对于 GIN 索引,有一个“快速更新”机制,但如果它被打开,那么它将适用于这两种情况。如果实现了更多/更好的类似“快速更新”的功能,它们可能会以类似的方式实现——这样它就可以改善这两种情况。
使用第一种方法的最大优点是它不需要在每次更新之间刷新 WAL,不需要解析/分析/计划每次更新,也不需要做 IPC/上下文交换/网络往返每次更新时发送给客户端。但是客户端可以通过使用显式事务、准备好的语句或流水线来改善这些问题。
如果值列表很长,将其放入哈希表然后读取所有目标表并用它探测哈希表可能会更快,而不是使用嵌套索引扫描对值列表进行循环目标表。使用第二种方法,即使速度较慢,它也被有效地强制执行嵌套循环。