2015-10-08 40 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