SQL SERVER 2008 R2を使用しています
SQLでAPPLYに出会ったばかりで、それが非常に多くのケースでクエリの問題を解決する方法を気に入っていました。
結果を得るために2つの左結合を使用していたテーブルの多くは、1つの外部適用で取得できました。
ローカルDBテーブルに少量のデータがあり、展開後、コードは少なくとも20倍大きなデータで実行されることになっています。
大量のデータの場合、外側の適用が左の2つの結合条件よりも長くかかる可能性があることを懸念しています。
適用がどのように正確に機能し、非常に大きなデータのパフォーマンスにどのように影響するかを誰かに教えてください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
誰でも正確に適用がどのように機能し、非常に大きなデータのパフォーマンスにどのように影響するか教えてくれますか
APPLY
は 相関結合 です(一部の製品およびSQL標準の新しいバージョンでは_LATERAL JOIN
_と呼ばれます)。他の論理構造と同様に、パフォーマンスに直接影響を与えることはありません。原則として、論理的に同等の構文を使用してクエリを記述でき、オプティマイザは入力をまったく同じ物理的な実行プランに変換します。
もちろん、これにはオプティマイザがすべての可能な変換を把握し、それぞれを検討する時間が必要です。このプロセスには現在の宇宙時代よりも時間がかかる可能性があるため、ほとんどの商用製品はこのアプローチを採用していません。したがって、クエリ構文は最終的なパフォーマンスに影響を与える可能性があり、実際に影響を及ぼしますが、どちらがより良いのか、なぜであるのかについての一般的な記述を行うことは困難です。
オプティマイザにはこのパターンを同等のJOIN
に変換するロジックが含まれていないため、OUTER APPLY ( SELECT TOP ... )
の特定の形式は、SQL Serverの現在のバージョンで相関ネストループ結合になる可能性が最も高くなります。外部入力が大きく、内部入力がインデックス付けされていない場合、または必要なページがまだメモリにない場合、相関のあるネストされたループ結合はうまく機能しない可能性があります。さらに、オプティマイザのコストモデルの特定の要素は、相関するネストされたループ結合が、意味的に同一のJOIN
よりも並列実行計画を生成する可能性が低いことを意味します。
単一の左結合とrow_number()で同じクエリを作成することができました
これは、一般的なケースではより良い場合とそうでない場合があります。代表的なデータを使用して、両方の選択肢をパフォーマンステストする必要があります。 _LEFT JOIN
_および_ROW_NUMBER
_の方が効率的である可能性は確かにありますが、選択した正確なクエリプランの形状によって異なります。このアプローチの効率に影響を与える主な要因は、必要な列をカバーし、_PARTITION BY
_および_ORDER BY
_句で必要な順序を提供するインデックスの可用性です。 2番目の要素は、テーブルのサイズです。クエリが関連するテーブルの比較的小さな部分に触れる場合、効率的で適切にインデックス付けされたAPPLY
は、最適なインデックス付けで_ROW_NUMBER
_よりも優れたパフォーマンスを発揮します。テストが必要です。
最初のクエリは、SQLサーバーへの1つの要求だけで並列実行できます。すべてのレコードをフェッチし、フィルター基準に基づいて出力を提供します。
ただし、2番目の場合は行ごとに実行され、各行についてTable2がスキャンされ、結果に追加されます。
外部クエリのレコード数が少ない場合は、2番目のクエリの方が適切です(外部適用)。ただし、最初のクエリでより多くのデータを取得できる場合は、最初のクエリを使用する必要があります。