sql >> データベース >  >> RDS >> Sqlserver

大きな行セットでの IN と JOIN

    更新:

    私のブログのこの記事は、私の回答と別の回答に対する私のコメントの両方を要約し、実際の実行計画を示しています。

    SELECT  *
    FROM    a
    WHERE   a.c IN (SELECT d FROM b)
    
    SELECT  a.*
    FROM    a
    JOIN    b
    ON      a.c = b.d
    

    これらのクエリは同等ではありません。テーブルが b の場合、異なる結果が得られる可能性があります キーは保存されません (つまり、b.d の値) 一意ではありません)。

    最初のクエリに相当するものは次のとおりです:

    SELECT  a.*
    FROM    a
    JOIN    (
            SELECT  DISTINCT d
            FROM    b
            ) bo
    ON      a.c = bo.d
    

    b.d の場合 UNIQUEです そのようにマークされています (UNIQUE INDEX を使用) または UNIQUE CONSTRAINT SQL Server であるため、これらのクエリは同一であり、おそらく同一のプランを使用します。

    SQL Server このクエリを実行するには、次のいずれかの方法を使用できます:

      <リ>

      a.c に索引がある場合 、 d UNIQUEです と b a に比べて比較的小さい 、次に条件がサブクエリとプレーンな INNER JOIN に伝播されます が使用されます (with b 先頭)

      <リ>

      b.d にインデックスがある場合 と d UNIQUE ではありません の場合、条件も伝播され、LEFT SEMI JOIN 使用されている。上記の条件にも使用できます。

      <リ>

      両方の b.d にインデックスがある場合 と a.c それらが大きい場合、MERGE SEMI JOIN 使用されています

      <リ>

      どのテーブルにもインデックスがない場合、b にハッシュ テーブルが作成されます。 および HASH SEMI JOIN

    どちらでもない これらのメソッドのうち、サブクエリ全体を毎回再評価します。

    この仕組みの詳細については、私のブログのこのエントリを参照してください:

    すべての RDBMS へのリンクがあります



    1. グリッドインフラストラクチャを再リンクする

    2. phpを使用して復号化できるmysqlにパスワードを保存するより良い方法

    3. インストール後、WAMPサーバーがWindows10で起動していません

    4. RawSQLクエリをLaravelEloquentに変換する