2017-03-15 10 views
5

この場合、クライアントから送信された文字列のリストがあるとします。コンプライアンス・リージョンと呼ばれる表があります。私は、名前のプロパティを持つ行を検索したいと地域の項目は、行に存在する必要があります。SQL INNER JOINとWhere Exists Performance Consideration

LINQでは、私は2つの異なる方法でそれを行うことができます。以下のように、2つの異なるSQLクエリを生成します。 私の質問は私が選ぶべきですか?どのクエリの方がパフォーマンスが良いですか?

List<string> regions = new List<string>() { "Canada", "EN 50530" }; 

      var cregions = from c in complianceRegions 
          from r in regions 
          where c.Name.Equals(r) 
          select c; 

      var cregions2 = from c in complianceRegions 
          where regions.Any(x => x == c.Name) 
          select c; 

生成されるSQLは、以下を示しています。

cregions

し、要求されたとして

--cregions2 
    SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[Description] AS [Description] 
    FROM [Administration].[ComplianceRegions] AS [Extent1] 
    WHERE EXISTS (SELECT 
     1 AS [C1] 
     FROM (SELECT 
      N'Canada' AS [C1] 
      FROM (SELECT 1 AS X) AS [SingleRowTable1] 
     UNION ALL 
      SELECT 
      N'EN 50530' AS [C1] 
      FROM (SELECT 1 AS X) AS [SingleRowTable2]) AS [UnionAll1] 
     WHERE [UnionAll1].[C1] = [Extent1].[Name] 
    ) 

cregions2 を追加しました実行計画

 -- cregions 
    SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[Description] AS [Description] 
    FROM [Administration].[ComplianceRegions] AS [Extent1] 
    INNER JOIN (SELECT 
     N'Canada' AS [C1] 
     FROM (SELECT 1 AS X) AS [SingleRowTable1] 
    UNION ALL 
     SELECT 
     N'EN 50530' AS [C1] 
     FROM (SELECT 1 AS X) AS [SingleRowTable2]) AS [UnionAll1] ON [Extent1].[Name] = [UnionAll1].[C1] 

+2

*パフォーマンスが優れているクエリはどれですか?*自分のテストで明らかになったことは何ですか? –

+0

興味深い部分は、私は同じクエリを何回か実行すると、SQLサーバーがクエリをキャッシュし、私に間違ったパフォーマンスを与えます。 –

+0

最初のクエリで 'Contains'と2番目の' == 'が使用されるのはなぜですか?どのような比較演算子ですか?現在、あなたはリンゴとオレンジを比較しています。 –

答えて

2

2つの選択肢がある場合、列名に関数呼び出しがないため、2番目の方が優れている可能性があります。

ただし、2つは同じではありません。最初は部分一致、後者は完全一致です。あなたは本当にあなたが意図していることをするべきです。パフォーマンスは精度に2次的です。

どちらも痛いです。 CHARINDEX()の出力をインデックスにキャスティングしますか? 「冗長」と言えますか?

彼らは、クエリが単純ではない理由を質問請う:

select . . . 
from [Administration].[ComplianceRegions] AS [Extent1] 
where Extent1.Name in (N'Canada', N'EN 50530'); 

これは、このロジックの最も簡単かつ最高のパフォーマンスのバージョンです。

+0

これらのクエリは自動生成されます。私はより良いLINQクエリを選択する必要があります。 –

+0

@FoyzulKarim:あなたは両方のクエリとスキーマの実行計画を貼り付ける必要がありますが、これに関係するテーブルの数はありません。この質問には答えられません – TheGameiswar

+0

*なぜ検索は単純ではないのですか?部分一致のために? –

0

@ JNKの回答in this postの引用。

EXISTS全体の他のテーブルを返しをJOIN

、ブール値を返すために使用されるEXISTSのみサブクエリ戻り結果、及び短絡場合とすぐにそれがないように試験するために使用されます。 JOINは、リレーションがある別のテーブルの追加のフィールドと組み合わせて結果セットを拡張するために使用されます。

あなたの例では、クエリはsymantically同等です。

一般的には、使用がときに存在する:あなたは関連テーブル からデータを返す必要はありません

あなたは、関連テーブルにdupesを持っている(JOINの値が繰り返された場合に重複した行を引き起こす可能性があります) あなたがしたいです存在をチェックする(LEFT OUTER JOIN ... NULL条件の代わりに使用する) 適切なインデックスがある場合、ほとんどの場合、EXISTSはJOINと同じように動作します。例外は非常に複雑なサブクエリであり、通常EXISTSを使用する方が速くなります。

あなたのJOINキーが索引付けされていない場合、EXISTSを使用する方が速いかもしれませんが、特定の状況でテストする必要があります。

JOIN構文は読みやすく、通常よりもはっきりしています。

0

これらのクエリは等しいです。そして、両方ともひどいです、私はそれらのいずれかを選択しませんでした。ハードコードされた値があるため、再利用することはできません。私は、SQL Serverの自動パラメータ化がそれを処理できるかどうか分からないので、実行計画キャッシュがおそらく苦しんでいます。適切なソリューションはテーブル値のパラメータを使用していますが、残念ながら私が知る限りlinqプロバイダではサポートされていません。だからあなた自身でクエリを作成する必要があります、あなたはlinqを使用して結果を具体化することができます。

Ivan Stoevによって提供されているソリューションを試すことができます。プロバイダが提供する内容によってどれくらい効果がありますか。 Linq2sqlは長いリストの場合、リスト内の多くの項目と同じ数のパラメータを生成するので、拡張されません。リスト内の項目数が同じ場合、少なくとも実行計画を再利用できます。