外部適用と左結合のパフォーマンス


37

SQL SERVER 2008 R2を使用しています

私はSQLでAPPLYに出会い、多くの場合にクエリの問題を解決する方法が大好きでした。

結果を取得するために2つの左結合を使用していたテーブルの多くは、1つの外部適用を取得できました。

ローカルDBテーブルに少量のデータがあり、展開後、コードは少なくとも20倍のデータで実行されるはずです。

大量のデータの場合、外部適用は2つの左結合条件よりも時間がかかることが心配です。

誰でも正確に適用がどのように機能し、それが非常に大きなデータのパフォーマンスにどのように影響するかを伝えることができますか?可能であれば、n1 ^ 1またはn1 ^ 2に比例するような各テーブルのサイズとの比例関係... n1はテーブル内の行数です1。

以下は、左結合が2つのクエリです。

select EC.*,DPD.* from Table1 eC left join
  (
   select member_id,parent_gid,child_gid,LOB,group_gid,MAX(table2_sid) mdsid from Table2
   group by member_id,parent_gid,child_gid,LOB,group_gid

  ) DPD2 on DPD2.parent_gid = Ec.parent_gid
        AND DPD2.child_gid = EC.child_gid
        AND DPD2.member_id = EC.member_id
        AND DPD2.LOB = EC.default_lob
        AND DPD2.group_gid = EC.group_gid
  left join
  Table2 dpd on dpd.parent_gid = dpd2.parent_gid 
            and dpd.child_gid = dpd2.child_gid
            and dpd.member_id = dpd2.member_id 
            and dpd.group_gid = dpd2.group_gid 
            and dpd.LOB = dpd2.LOB
            and dpd.table2_sid = dpd2.mdsid

これが外部適用のクエリです

select * from Table1 ec   
OUTER APPLY (
      select top 1 grace_begin_date,retroactive_begin_date,Isretroactive
                    from Table2 DPD 
                    where DPD.parent_gid = Ec.parent_gid
                    AND DPD.child_gid = EC.child_gid
                    AND DPD.member_id = EC.member_id
                    AND DPD.LOB = EC.default_lob
                    AND DPD.group_gid = EC.group_gid
                    order by DPD.table2_sid desc
     ) DPD 

回答:


44

誰でも正確に適用がどのように機能し、非常に大きなデータのパフォーマンスにどのように影響するかを伝えることができますか?

APPLY相関結合ですLATERAL JOIN一部の製品およびSQL Standardの新しいバージョンではa と呼ばれます)。他の論理構造と同様に、パフォーマンスには直接影響しません。原則として、論理的に同等の構文を使用してクエリを記述できる必要があり、オプティマイザーは入力をまったく同じ物理実行プランに変換します。

もちろん、これにはオプティマイザーが可能なすべての変換を把握し、各変換を検討する時間が必要です。このプロセスは、宇宙の現在の時代よりも長くかかる可能性があるため、ほとんどの市販製品はこのアプローチを採用していません。したがって、クエリ構文は最終的なパフォーマンスに影響を与える可能性があり、多くの場合、影響を及ぼしますが、どちらが優れているのか、なぜかについての一般的なステートメントを作成するのは困難です。

OUTER APPLY ( SELECT TOP ... )オプティマイザにはこのパターンを同等のパターンに変換するロジックが含まれていないため、SQL Serverの現在のバージョンでは、特定の形式の結果、相関するネストされたループが結合される可能性が最も高くなりますJOIN。外部入力が大きく、内部入力のインデックスが作成されていない場合、または必要なページがまだメモリにない場合、相関するネストされたループの結合はうまく機能しない場合があります。さらに、オプティマイザーのコストモデルの特定の要素は、相関するネストされたループの結合がJOIN、並列実行プランを生成するために意味的に同一である可能性が低いことを意味します。

単一の左結合とrow_number()で同じクエリを作成できました

これは、一般的なケースではより良い場合とそうでない場合があります。代表データを使用して、両方の選択肢をパフォーマンステストする必要があります。LEFT JOINそしてROW_NUMBER、確かに、より効率的になる可能性を持っていますが、それは、選択された正確なクエリプランの形状に依存します。このアプローチの効率に影響する主な要因は、必要な列をカバーし、PARTITION BYand ORDER BY句で必要な順序を提供するインデックスの可用性です。2番目の要因は、テーブルのサイズです。クエリが関係するテーブルの比較的小さな部分に触れる場合、効率的で適切にインデックス付けされたインデックスAPPLYROW_NUMBER、最適なインデックス付けでパフォーマンスを向上させることができます。テストが必要です。


2

最初のクエリは、SQLサーバーへの1つの要求のみで並行して実行できます。すべてのレコードをフェッチし、フィルター条件に基づいて出力を提供します。

ただし、2番目の場合、行ごとに実行され、各行に対してTable2がスキャンされ、結果に追加されます。

外部クエリのレコードが少ない場合は、2番目のレコードの方が優れています(外部適用)。ただし、最初のクエリでより多くのデータを取得できる場合は、最初のクエリを使用する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.