我试图在postgresql中获得两个几乎相同的表之间的差异。我正在运行的当前查询是:
SELECT * FROM tableA EXCEPT SELECT * FROM tableB;
和
SELECT * FROM tableB EXCEPT SELECT * FROM tableA;
上述每个查询大约需要2分钟(大表)
我希望将两个查询结合起来以节省时间,所以我尝试了:
SELECT * FROM tableA EXCEPT SELECT * FROM tableB
UNION
SELECT * FROM tableB EXCEPT SELECT * FROM tableA;
虽然它有效但运行需要20分钟!我猜它最多需要4分钟,即每个查询单独运行的时间。
UNION正在做一些额外的工作,这需要花费这么长时间吗?或者有什么方法可以加快速度(有或没有UNION)?
更新:使用UNION ALL运行查询需要15分钟,几乎是自己运行每个查询的4倍,我是否正确地说UNION(全部)根本不会加快速度?
答案 0 :(得分:15)
关于你的“额外工作”问题。是。 Union不仅结合了两个查询,还通过并删除了重复项。它与使用不同的陈述相同。
出于这个原因,特别是与你的except语句相结合,“union all”可能会更快。
在这里阅读更多内容: http://www.postgresql.org/files/documentation/books/aw_pgsql/node80.html
答案 1 :(得分:3)
除了组合第一个和第二个查询的结果外,默认情况下UNION
也会删除重复记录。 (见http://www.postgresql.org/docs/8.1/static/sql-select.html)。检查两个查询之间的重复记录所涉及的额外工作可能是额外时间的原因。在这种情况下,不应该有任何重复记录,因此可以通过指定UNION ALL
来避免寻找重复项的额外工作。
SELECT * FROM tableA EXCEPT SELECT * FROM tableB
UNION ALL
SELECT * FROM tableB EXCEPT SELECT * FROM tableA;
答案 2 :(得分:2)
我认为您的代码不会返回您想要的结果集。我宁愿认为你想这样做:
SELECT *
FROM (
SELECT * FROM tableA
EXCEPT
SELECT * FROM tableB
) AS T1
UNION
SELECT *
FROM (
SELECT * FROM tableB
EXCEPT
SELECT * FROM tableA
) AS T2;
换句话说,您需要一组互斥的成员。如果是这样,您需要在SQL中阅读关系运算符优先级;)如果有,您可能会意识到上述内容可以合理化为:
SELECT * FROM tableA
UNION
SELECT * FROM tableB
EXCEPT
SELECT * FROM tableA
INTERSECT
SELECT * FROM tableB;
FWIW,使用子查询(派生表T1
和T2
)明确显示(否则会隐含)关系运算符优先级,原始查询是这样的:
SELECT *
FROM (
SELECT *
FROM (
SELECT *
FROM tableA
EXCEPT
SELECT *
FROM tableB
) AS T2
UNION
SELECT *
FROM tableB
) AS T1
EXCEPT
SELECT *
FROM tableA;
上述内容可以与:
相关联SELECT *
FROM tableB
EXCEPT
SELECT *
FROM tableA;
......我认为不是意图。
答案 3 :(得分:-2)
您可以使用tableA FULL OUTER JOIN tableB,它可以提供您想要的(使用propre连接条件)只有1个表扫描,它可能比上面的2个查询更快。
请发布更多信息。