大きなテーブルから行のサブセットを返すためにCTEで開始するテーブル値UDFを作成しました。CTEにはいくつかの結合があります。内側の2つと左側の1つは、多くの行を含まない他のテーブルに結合します。CTEには、必要な行のみを返すために、日付範囲内の行を返すwhere句があります。
次に、さまざまな基準を使用して小計を作成するために、このCTEを4つの自己左結合で参照しています。
クエリは非常に複雑ですが、ここにその簡略化された疑似バージョンがあります
WITH DataCTE as
(
SELECT [columns] FROM table
INNER JOIN table2
ON [...]
INNER JOIN table3
ON [...]
LEFT JOIN table3
ON [...]
)
SELECT [aggregates_columns of each subset] FROM DataCTE Main
LEFT JOIN DataCTE BananasSubset
ON [...]
AND Product = 'Bananas'
AND Quality = 100
LEFT JOIN DataCTE DamagedBananasSubset
ON [...]
AND Product = 'Bananas'
AND Quality < 20
LEFT JOIN DataCTE MangosSubset
ON [...]
GROUP BY [
SQL Serverが混乱し、自己結合ごとにCTEを呼び出すように感じます。これは、実行プランを見ると確認できたようですが、それらを読むのは専門家ではないと自白しています。
SQL Serverは、CTEからのデータ取得を数回ではなく、1回だけ実行するのに十分スマートであると想定していました。
同じアプローチを試しましたが、CTEを使用してデータのサブセットを取得するのではなく、CTEと同じselectクエリを使用しましたが、代わりに一時テーブルに出力しました。
CTEバージョンを参照するバージョンは40秒かかります。一時テーブルを参照するバージョンには、1〜2秒かかります。
SQL ServerがCTEの結果をメモリに保持するのに十分スマートでないのはなぜですか?
特にこの場合、UDFはテーブル値であるため、CTEが好きです。そのため、すべてを1つのステートメントにまとめることができました。
一時テーブルを使用するには、UDF値のマルチステートメントテーブルを作成する必要がありますが、これは少し洗練されていないソリューションです。
CTEでこの種のパフォーマンスの問題が発生した方もいらっしゃいましたか?もしそうなら、どのようにしてそれらを分類しましたか?
ありがとう、
カルロス