しばらく前に、Brent OzarがSQL ServerとPostgreSQLの違いのいくつかを詳しく説明した投稿を公開しました。
SQL ServerとPostgreSQLの2つの重要な違い
最初のポイント(「CTEは最適化のフェンス」)が私の目を引きました。提供されている例では、SQL ServerがCTEとメインクエリを組み合わせ、それを単一のクエリとして最適化している( PostgreSQL)。
ただし、この動作は、他のブログやトレーニングクラスでSQL ServerがCTEを最適化フェンスとして扱い、インデックスの使用やパフォーマンスの向上などを可能にする例とは対照的です。次に例を示します。
したがって、SQL ServerはCTEを最適化のフェンスとして「称賛」しているようです。 SQL ServerがCTEを最適化フェンスとして確実に尊重する既知のケース(またはその逆の振る舞い)の特定のリストを文書化した優れたリソースはありますか?
... SQL ServerがCTEを最適化フェンスとして確実に尊重する既知のケースのリスト
このようなリストは、信頼性を保証することなく、観察された動作に依存します。
SQL Serverクエリオプティマイザーは、一般的なテーブル式を最適化フェンス自体として処理することはありません。再帰CTEはこの良い例です。
CTEは、ビュー/インライン関数/サブクエリ/派生テーブルと非常によく似ており、クエリにインライン化されます。観察された「フェンス」の動作は、オプティマイザが原理内の透過境界を越えて最適化できないか、最適化できないかによって異なります。
一般的に言えば、CTEがより単純で「リレーショナル」であるほど、オプティマイザがビットを移動できる可能性が高くなります。
オプティマイザがCTEの「結果」を考慮したり強制したりできるようにする機能が提案されていますが、まだ実装されていません。
それまでの間、最も一般的な回避策は、一時テーブルまたはテーブル変数で中間結果セットを明示的に具体化することです。これには明らかに、単一のステートメントに限定されないシナリオが必要です。