MS SQL Server が を処理する方法に問題があることがわかりましたCROSS APPLY
。
私が使用しているデータベースには、次のスキーマの価格設定システムがあります。
サービス -> 価格モデル <- 価格コンポーネント ( 「->」はテーブルを指す外部キーを示します)
一部の価格モデルには「段階的価格設定」があります。つまり、金額パラメーターがさまざまなしきい値に達すると、価格が上昇します (1 ~ 3 単位は価格 A、4 ~ 8 単位は価格 B など)。
私が抱えている問題は、INNER JOIN
[Price Model ID] の [Service] と [Price Component] の間で重複行が生成されることです。これは、Price Component の価格を実際に使用していないため、表の別のフィールドにすぎないためです。 [Price Component] 行の各行で同じです。
SELECT *
FROM [Service] s
INNER JOIN [Price Component] pc
ON s.[Price Model Id] = pc.[Price Model Id]
この問題の論理的な修正は、これを行う を に置き換えることINNER JOIN
ですCROSS APPLY
。
SELECT *
FROM [Service] s
CROSS APPLY (SELECT TOP 1 *
FROM [Price Component] pc
WHERE s.[Price Model Id] = pc.[Price Model Id]
) AS pc
問題は、この変更とは一見関係のない他のいくつかの結合で効率が完全に破壊されていることです。実行計画を見ると、以前は 2.3 サイクルかかっていた結合に 480 万サイクルかかっています。
元のクエリに a を追加しようとしましたDISTINCT
([Price Component] テーブルからの一意のデータを使用しないため、実行時間が 4 倍になることを除いて、これは関数ソリューションです。必要な値だけを返そうとしました。 [価格コンポーネント] テーブルから、しかしそれはあまり役に立たないようです:
SELECT *
FROM [Service] s
CROSS APPLY (SELECT DISTINCT pc.moneyUnitId
FROM [Price Component] pc
WHERE s.[Price Model Id] = pc.[Price Model Id]
) AS pc
奇妙なことに、CROSS APPLY
を anに変更するOUTER APPLY
と、他の結合の問題は修正されますが、CROSS APPLY の目的が無効になります (これは、基本的に anINNER JOIN
と anの違いであると理解していOUTER JOIN
ます)。
での複雑さの異常な増加を引き起こしている可能性があるものについて、誰か考えや洞察を持っていCROSS APPLY
ますか?
アップデート
したがって、実行計画の解釈方法についてさらに読んだ後、次のことを学びました。
元のクエリ (
INNER JOIN
s を使用) は、与えられたフィルター データで始まる長い一連の入れ子になったループです。フィルターがインデックス付きフィールドにある限り、応答時間はかなり迅速です。変更されたクエリ (を使用
CROSS APPLY
) は、より長い一連のハッシュ マッチであり、指定したすべてのテーブル (フィルターを除く) を結合し、最後にフィルターを適用します。常に死よりも遅い。変更されたクエリ (を使用
OUTER APPLY
) を使用すると、元のクエリと同じことを実行できますが、WHERE 句と一致しない結果は除外されません。オリジナルと同じくらいきびきび。
CROSS APPLY
問題は、要求されたフィルターの前にすべてのテーブルを結合するように計画を変更するのはなぜですか?