2011-06-13 52 views
7

我試圖在postgresql中的兩個幾乎相同的表之間得到差異。我當前運行的查詢是:Postgresql UNION需要運行單個查詢的時間長達10倍​​

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 ALL運行查詢需要15分鐘,幾乎是自己運行每個的4倍,我是否正確地說UNION(全部)不會加快速度?

+0

單個tableA或tableB中是否有重複項需要省略?否則,請嘗試「聯合所有」。 – 2011-06-13 23:59:44

+0

@ScrumMeister:我之前沒有想過這個。聯合會刪除來自單個表的重複項嗎?我認爲它只刪除了兩個聯合表之間的重複項。我可能不得不研究這一點。 – RThomas 2011-06-14 00:20:58

+0

你可以發佈'EXPLAIN ANALYZE'的輸出嗎? – 2011-06-14 06:00:23

回答

11

關於您的「額外工作」問題。是。 Union不僅結合了這兩個查詢,而且還通過並刪除了重複項。這與使用不同的陳述是一樣的。

由於這個原因,特別是與你的除外聲明「union all」結合起來可能會更快。

更多在這裏閱讀: http://www.postgresql.org/files/documentation/books/aw_pgsql/node80.html

+0

我剛剛運行「SELECT * FROM tableA EXCEPT SELECT * FROM tableB UNION ALL SELECT * FROM tableB EXCEPT SELECT * FROM tableA;」花了15分鐘,所以它仍然沒有分開運行兩個查詢那麼快。 – lanrat 2011-06-14 01:03:13

+0

我選擇這個作爲正確的答案,但它似乎仍然分別運行查詢加快了速度。 – lanrat 2011-06-14 02:22:51

+0

@RThomas通過增加union all來增加冗餘值,如果我想要不同的值呢? – Lokesh 2018-01-08 06:17:04

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; 
+0

似乎我得到我的答案輸入有點慢。榮譽lazyDBA – dave 2011-06-14 00:23:47

-2

你可以使用表A FULL OUTER JOIN tableB的,它會給你想要的東西(用黑白配的連接條件),只有1次掃描,它可能會比上述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,使用子查詢(派生表T1T2)明確顯示(否則這將是隱含的)關係運算符的優先級,你原來的查詢是這樣的:

SELECT * 
    FROM (
     SELECT * 
      FROM (
       SELECT * 
        FROM tableA 
       EXCEPT 
       SELECT * 
        FROM tableB 
       ) AS T2 
     UNION 
     SELECT * 
      FROM tableB 
     ) AS T1 
EXCEPT 
SELECT * 
    FROM tableA; 

以上可以relationalised到:

SELECT * 
    FROM tableB 
EXCEPT 
SELECT * 
    FROM tableA; 

...我想不是什麼意圖。

+0

感謝您的解釋!我運行了您提供的第一個查詢,但運行這兩個單獨的查詢所花的時間仍然很長。我正在運行的兩個查詢正是我想要的;我只是希望它更快:)。您提供的第二個查詢花費了> 1小時,所以我停止了它(所有其他所有在10分鐘以內的地方) – lanrat 2011-06-16 01:03:06

相關問題