2011-06-13 12 views
7

私はpostgresqlのほぼ同じ2つのテーブルの差分を取得しようとしています。私が実行している現在のクエリは次のとおりです。PostgreSQL UNIONは個々のクエリを実行するのに10倍の時間がかかります

SELECT * FROM tableA EXCEPT SELECT * FROM tableB; 

SELECT * FROM tableB EXCEPT SELECT * FROM tableA; 

上記のクエリはそれぞれ、(その大きなテーブル)を実行するのに約2分かかり

私は2つを組み合わせてみたかったですクエリは時間を節約することを期待しているので、私は試しました:

SELECT * FROM tableA EXCEPT SELECT * FROM tableB 
UNION 
SELECT * FROM tableB EXCEPT SELECT * FROM tableA; 

そして、それが動作している間、実行するには20分かかります!私はそれが最大で4分、それぞれのクエリを個別に実行する時間がかかると思うだろう。

UNIONが行っている余分な作業は、それが長くかかるようになっていますか?または、これを(UNIONの有無に関わらず)スピードアップできる方法はありますか?

UPDATE:UNION ALLでクエリを実行すると、それぞれのクエリを実行するのに要する時間の約4倍の15分かかります.Union(すべて)がこれをまったくスピードアップしないと言うのは正しいですか?

+0

'tableA'または' tableB'だけに省略が必要な重複がありますか?それ以外の場合は 'UNION ALL'を試してください。 –

+0

@ScrumMeister:私は以前これを考えていませんでした。 unionは、単一のテーブルからの重複を削除しますか?私はそれが2つのユニオンテーブル間の重複を削除しただけだと思った。私はそれを研究しなければならないかもしれない。 – RThomas

+0

'EXPLAIN ANALYZE'の出力を投稿できますか? –

答えて

11

あなたの「余分な仕事」に関する質問。はい。 Unionは2つのクエリを結合するだけでなく、重複を排除して削除します。それは別個のステートメントを使用するのと同じです。

このため、特にあなたのexcept文「union all」と組み合わされると、より速くなる可能性があります。もっとここに

読む:最初と2番目のクエリの結果を結合することに加え http://www.postgresql.org/files/documentation/books/aw_pgsql/node80.html

+0

私は "SELECT * FROM tableA SELECT * FROM tableB UNION ALL SELECT * FROM tableB EXCEPT SELECT * FROM tableA;"を実行しました。それは15分かかったので、まだ2つのクエリを別々に実行するほど速くはありません。 – lanrat

+0

これを正解として選択していますが、依然としてクエリを実行するだけでスピードアップするようです。 – lanrat

+0

@RThomasに 'union all 'を追加すると、冗長値が追加され、別の値が必要な場合はどうなりますか? – Lokesh

3

、デフォルトでUNIONも重複したレコードを削除します。 (http://www.postgresql.org/docs/8.1/static/sql-select.html参照)。 2つのクエリ間で重複したレコードをチェックするのに必要な余分な作業はおそらく余分な時間の原因となります。このような状況では重複レコードは存在しないので、重複を探す余分な作業は避けることができます。UNION ALLを指定します。

SELECT * FROM tableA EXCEPT SELECT * FROM tableB 
UNION ALL 
SELECT * FROM tableB EXCEPT SELECT * FROM tableA; 
+0

私は私の答えを入力するのが少し遅かったようだ。忠実なlazyDBAへ – dave

-2

あなたがにtableA FULL OUTERのみ1回のテーブルスキャンを使用すると、(propreと結合条件を)望むものを与えるだろうTABLEBを、JOINを使用することができ、それはおそらく、上記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でリレーショナル演算子の優先順位をよく読んでする必要があります。)そして、あなたが持っているとき、あなたは上記に合理化することができます実現することができる:サブクエリ(派生テーブルT1を使用して、

SELECT * FROM tableA 
UNION 
SELECT * FROM tableB 
EXCEPT 
SELECT * FROM tableA 
INTERSECT 
SELECT * FROM tableB; 

FWIWとT2)が明示的に(何がそうでない場合は、暗黙のだろう)関係演算子の優先順位を表示するには、元のクエリはこれです:

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

説明ありがとう!あなたが提供した最初のクエリを実行しましたが、2つの個別クエリを実行するよりもまだ時間がかかります。私が実行している2つのクエリは、まさに私が望むものです。私はちょうどそれがより速くしたい:)。あなたが提供した2番目のクエリは> 1時間を要したので、私はそれを止めました(10分以内の他のすべての場所) – lanrat

関連する問題