2009-05-12 7 views
3

テーブルを結合するとき(以下の例のように)、テーブルの結合と必要な列のみを含むサブクエリの結合の効率は異なりますか?テーブル結合の効率の問題

つまり、これらの2つのテーブルの間に効率に違いはありますか?

SELECT result 
    FROM result_tbl 
    JOIN test_tbl     USING (test_id) 
    JOIN sample_tbl     USING (sample_id) 
    JOIN (SELECT request_id 
      FROM request_tbl 
     WHERE request_status='A') USING(request_id) 

SELECT result 
    FROM (SELECT result, test_id FROM result_tbl) 
    JOIN (SELECT test_id, sample_id FROM test_tbl) USING(test_id) 
    JOIN (SELECT sample_id   FROM sample_tbl) USING(sample_id) 
    JOIN (SELECT request_id 
      FROM request_tbl 
     WHERE request_status='A')     USING(request_id) 
+0

良い質問 - 誰かにもっと知識豊かな答えをさせてくれますが、DBエンジンは両方のケースで同じ数の列に参加する必要があるため、2つは効率について同じです同じ数の行で(たとえフィールドの数が少なくても)。私が間違っているなら私を訂正してください! – AndreiM

+0

マーク・ブラディはこの質問を愛していただろうが、nooooo ....ここのエリートたちは、彼の力を握って彼を怖がっていた。 – TheSoftwareJedi

+0

この問題は、SQLサーバーがより優れていることを誰もが知っており、私たちはこれを尋ねる必要さえないので、関連性がなくなったので閉じます。 – TheSoftwareJedi

答えて

4

対それは問題ではありません。あなたが一般的に最もよく知っているオプティマイザから制御を外しているので、実際にはワーズになるかもしれません。

しかし、JOINを実行していて、EXISTSステートメントのシリーズとして書き直すのがQUITE OFTENより優れているテーブルの1つの列のみを含めることを覚えておいてください。 JOIN(いくつかの例外を除いて)は、オプティマイザが行うより多くの作業である一致する行に参加します。

SELECT t1.id1 
    FROM table1 t1 
INNER JOIN table2 ON something = something 

はほとんどの場合、オプティマイザは、同一のものに問い合わせ計画を減らすことができる単純なクエリの場合

SELECT id1 
    FROM table1 t1 
WHERE EXISTS(SELECT * 
       FROM table2 
       WHERE something = something) 

でなければなりません。あなたのDBMSでそれをチェックしてください。

も、このコードの臭いであり、おそらく変更する必要があります。

がJOIN

SELECT result 
    FROM request 
WHERE EXISTS(...) 
    AND request_status = 'A' 
5

唯一の方法に(WHERE request_status = 'A' request_tbl FROM REQUEST_ID 選択します)トレースをオンにして両方を実行してから、トレースファイルを確認することを確認してください。ただし、オプティマイザはすべてのインラインビューをメインステートメントにマージし、同じクエリプランを作成します。

2

違いはありません。

EXPLAIN PLANを両方のステートメントで実行するとわかります。必要なデータを取得するのに必要な最小限のものしかないので、Oracleは「結果」の列をすべて知っています。同一である。

Oracleオプティマイザはサブクエリを実行します(サブクエリを実行して後で再利用するために結果をメモリに保持します)が、これはまれであり、パフォーマンスが向上するとオプティマイザが判断した場合にのみ発生します;いずれにしても、サブクエリで列を指定したかどうかに関わらず、Oracleはこの「マテリアライゼーション」を行います。

「結果」列が格納されている唯一の場所がブロック内にあれば(残りのデータとともに)、Oracleはそれらのブロックを参照する必要がありますが、関連する情報(「結果」列)列および他の関連する列、例えば「test_id」)を照会の処理中にメモリに記憶する。