0

次の 2 つの SQL ステートメントのうち、ほとんどの場合に時間がかからないのはどれですか?
1)

SELECT table_a.foo,
       table_b.zoo
FROM   table_a,
       table_b
WHERE  table_a.id = table_b.id
       AND table_b.bar = 'something'

2)

SELECT table_a.foo,
       tableb.zoo
FROM   table_a,
       (SELECT *
        FROM   table_b
        WHERE  bar = 'something') AS tableb
WHERE  table_a.id = tableb.id 

それとも同じですか?
(2)の方が速いようです...

4

3 に答える 3

5

他の回答とコメントは、推測または一般化しています。

本当の答えは、次のようないくつかの要因に依存するということです。

  • SQL オプティマイザの実装; どのブランドの RDBMS を使用していますか? MySQL? マイクロソフト SQL サーバー? オラクル?質問に適切なブランドのタグを付ける必要があります。

  • 関連するインデックスを含むテーブル定義。

  • テーブルのサイズ、および条件に一致するテーブルのサブセットのサイズ。

  • キャッシュのサイズに対するデータのサイズ。

@Colin'tHart がコメントで言及しているように、SQL が抽象的で宣言的な言語であること事実です。したがって、同じ結果を生成する 2 つの異なるクエリを宣言できるはずであり、RDBMS はそれをそのデータを収集する最適な方法に変換する必要があります。理論的には問題ありませんが、実際には、ソフトウェア設計者がコードを実装したケースの数に応じて魔法が効果を発揮します。

したがって、この質問のタイトルで言及する非常に基本的な一般的な sql (効率) プリンシパルは次のようになります。

パフォーマンスを測定します。推測したり、一般化したりしないでください。

これをさらに調査するには、クエリを実行するためにテーブルとインデックスにアクセスする方法について、SQL オプティマイザーからレポートを取得する必要があります。ほとんどの RDBMS 製品には、EXPLAINと呼ばれる文のバリエーションがあり、特定のクエリについてこのレポートを取得できます。RDBMS がこのケースを抽象化することに成功した場合、EXPLAIN レポートは、表示する両方のクエリ例で同一になるはずです。

たとえば、テスト用の MySQL データベースに対して同様のクエリを試しました。EXPLAIN は、派生テーブルのサブクエリを実行するための追加の手順があることを示しています。このサブクエリは、一致する行を検索するために使用されます。

mysql> EXPLAIN SELECT c.*, t.* FROM cast_info c 
JOIN ( SELECT * FROM title WHERE title = 'Star Wars') t ON c.movie_id = t.id\G

*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: <derived2>
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 8
        Extra: NULL
*************************** 2. row ***************************
           id: 1
  select_type: PRIMARY
        table: c
         type: ref
possible_keys: movie_id
          key: movie_id
      key_len: 4
          ref: t.id
         rows: 9
        Extra: NULL
*************************** 3. row ***************************
           id: 2
  select_type: DERIVED
        table: title
         type: ref
possible_keys: title
          key: title
      key_len: 152
          ref: const
         rows: 8
        Extra: Using where

サブクエリなしで単純な結合を行うのは少し異なります。同じテーブルを最初に検索しますが、派生テーブルとして扱う必要はありません。

mysql> EXPLAIN SELECT c.*, t.* FROM cast_info c 
JOIN title t ON c.movie_id = t.id WHERE title = 'Star Wars'\G

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t
         type: ref
possible_keys: PRIMARY,title
          key: title
      key_len: 152
          ref: const
         rows: 8
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: c
         type: ref
possible_keys: movie_id
          key: movie_id
      key_len: 4
          ref: imdb.t.id
         rows: 9
        Extra: NULL

SQL-89 (コンマ スタイル) 結合構文を使用すると、次のJOIN構文を使用したクエリと同じように扱われます。

mysql> EXPLAIN SELECT c.*, t.* FROM cast_info c, title t 
WHERE c.movie_id = t.id AND title = 'Star Wars'\G

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t
         type: ref
possible_keys: PRIMARY,title
          key: title
      key_len: 152
          ref: const
         rows: 8
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: c
         type: ref
possible_keys: movie_id
          key: movie_id
      key_len: 4
          ref: imdb.t.id
         rows: 9
        Extra: NULL

これは、MySQL の結果です。別の RDBMS のオプティマイザは異なる動作をする可能性があり、その EXPLAIN の出力は確かに異なって見えます。ポイントは、クエリの最適化プランを自分でテストするために使用できるツールがあることです。

EXPLAIN レポートはそのようなツールの1 つです。しかし EXPLAIN は通常、実際にクエリを実行せずに、オプティマイザーが何をしようとしているのかを示すだけです。プロファイラーツールを使用してクエリを実行し、実行時間をより正確に測定することもできます。使用できるプロファイラー ツールは、RDBMS のブランドによって異なります。

于 2013-10-08T15:09:58.787 に答える
-1

私の理解によれば、クエリ1は時間がかかりません.2番目のクエリでは

SELECT *
        FROM   table_b
        WHERE  bar = 'something'

最初に実行され、次に外側のクエリとクロスチェックされます。

于 2013-10-08T14:39:33.727 に答える