【发布时间】:2014-01-27 11:57:03
【问题描述】:
在 Postgres 数据库中,以下两个查询在 性能 方面是否等效?每个人都说“连接总是比子查询快”,但是 Postgres 查询计划器是否在幕后将子查询优化为连接?
查询 1:
UPDATE table_a
SET col_1 = 'a fixed value'
WHERE col_2 IN (
SELECT col_2 FROM table_b
);
解释计划:
更新 table_a(成本=0.00..9316.10 行=1 宽度=827) -> 嵌套循环半连接(成本=0.00..9316.10 行=1 宽度=827) -> table_a 上的 Seq Scan(成本=0.00..9287.20 行=1 宽度=821) -> 在 table_b 上使用 idx_table_b 进行索引扫描(成本=0.00..14.45 行=1 宽度=14) 索引条件:(col_2 = (table_a.col_2)::numeric)查询 2:
UPDATE table_a ta
SET col_1 = 'a fixed value'
FROM table_b tb
WHERE ta.col_2 = tb.col_2;
解释计划:
更新 table_ata(成本=0.00..9301.67 行=1 宽度=827) -> 嵌套循环(成本=0.00..9301.67 行=1 宽度=827) -> table_ata 上的 Seq 扫描(成本=0.00..9287.20 行=1 宽度=821) -> 在 table_b tb 上使用 idx_table_b 进行索引扫描(成本=0.00..14.45 行=1 宽度=14) 索引条件:(col_2 = (ta.col_2)::numeric)我相信它们在结果上是等效的(如果我错了,请提醒我)。我用大量数据尝试了几个解释计划。在更新完整表和将 table_a.col_2 限制为一个小子集时,它们的性能似乎相当。
我想确定我没有遗漏任何东西。如果它们是等价的,你会选择哪一个?为什么?
【问题讨论】:
-
它们的功能是否相同?在第一种情况下,只会更新匹配的行,其他行将保留它们的值。在第二种情况下,不匹配的行将变为
NULL -
@hashbrown 不正确。我刚刚测试过 - 不匹配的行将不会变成
NULL。您一定对第三种可能的构造感到困惑:UPDATE table_a SET col_1 = (SELECT 'a fixed value' FROM table_b where table_a.col_2 = table_b.col_2)。在这个构造中,是的,不匹配的行将变成NULL并且col_2必须是唯一的。 -
如果您一直在查看解释输出,请包含它!此外,提供有用的表定义和虚拟数据来匹配您的查询,这样我们就不必编造这些东西了。
标签: sql performance postgresql join subquery