2015-10-08 43 views
-1

我想从多个表中检索id的完整列表,它们可以完全重叠或相互排斥。我想知道哪个会有更好的性能,哪个是PostgreSQL的正确途径,为什么会这样呢?PostgreSQL:选择不同的ID联合与选择ID完全联接

说我有4个表,和表索引为优化:

[SELECT DISTINCT ... UNION]

SELECT DISTINCT id from table1 
UNION 
SELECT DISTINCT id from table2 
UNION 
SELECT DISTINCT id from table3 
UNION 
SELECT DISTINCT id from table4 
; 

[SELECT ... FULL JOIN]

SELECT DISTINCT coalesce(a.id, b.id, c.id, d.id) AS id 
FROM table1 a 
FULL JOIN table2 b on a.id=b.id 
FULL JOIN table3 c on b.id=c.id 
FULL JOIN table4 d on c.id=d.id 
; 

这里做了一些调整。感谢@ Hogan在他的回答中的建议。

注意

我对full join整个动机是因为id字段可以表之间的完全重叠。 full join可能会缓解一些表扫描。

+0

这些不一样 – Hogan

+0

没有必要用'UNION'区分。 'UNION'返回不同的值。 'UNION ALL'返回所有值 – lad2025

+0

@ lad2025。 。 。没有必要,但是在某些情况下,它可以产生更好的执行计划(即,当索引可以用于子查询中的“distinct”)时。也就是说,这两个查询是不相同的,所以我怀疑OP是否知道这个细微差别。 –

回答

0

这两者并不等价。第一个是你想要的;第二个不是。从这个角度来看,“表现”奖是第一个:正确的结果击败了更快的查询。

这解决了第二个版本:

SELECT id 
from table1 a FULL JOIN 
    table2 b 
    using (id) FULL JOIN 
    table3 c 
    using (id) FULL JOIN 
    table4 
    using (id); 

(你只需要distinct如果一个表可以有多个ID)

与任何性能问题,您应该与您的数据上尝试你的系统。

+0

这看起来不正确,它如何知道选择原因(可能是postgresql的功能,我不知道)是什么表'ID'? – Hogan

+0

每个连接中的使用部分告诉数据库这些列是相同的。我把它作为标准的一部分记住了,但从来没有见过它,除了postgresql –

+0

@Aツ - 我总是看到用作连接的捷径而不是“相同”,因为这些值不会与一个完整的连接 - 一些将是空的。 – Hogan

0

基于上面的评论,我会推荐以下内容 - 我认为这将是最有可能给服务器提供最佳机会来优化过程的良好性能。我没有做任何测试,并且不会有任何东西来支持这一行动预计的经验和直觉:

  1. 与ID类型的单个列创建临时表。向此列添加索引。

  2. 对于第一个表,选择所有的id并插入到这个表中。

  3. 对于下列每个表,选择除临时表外的所有ID(例如不在)并插入临时表。

  4. 使用临时表执行您的实际查询。


你的第二个查询是不一样的。我相信这就是你的意思

SELECT DISTINCT coalesce(a.id,b.id,c.id,d.id) as id 
from table1 a 
FULL JOIN table2 b on a.id=b.id 
FULL JOIN table3 c on b.id=c.id 
FULL JOIN table4 d on c.id=d.id 

这样def。看起来很丑,我需要进行测试,看看它是否比较慢,我期望一个好的优化器在两者上都有相同的性能。

+0

哦,是的,你是对的。这就是我的意思。我将编辑该问题。 – Boxuan