このフィドルを見てください: http://sqlfiddle.com/#!6/18324/2
view に対するクエリの最初の実行計画を展開しますB
。
最初のクエリはインデックス シークを使用して実行され、2 番目のクエリはインデックス スキャンを使用して実行されることに注意してください。私の実際のセットアップでは、何千行もあるため、かなりのパフォーマンス ヒットが発生します。
なんだ???
クエリは同等ですよね?リテラルがシークと変数 - スキャンを生成するのはなぜですか?
しかし、もっと重要なのは、どうすればこれを回避できますか?
この投稿は問題に最も近いものであり、そこから機能する解決策は使用していoption(recompile)
ます (ありがとう、Martin Smith)。ただし、クエリは ORM ライブラリ (Entity Framework) によって生成されており、手動で修正できないため、これはうまくいきません。
むしろ、私が探しているのはB
、問題が発生しないようにビューを再定式化する方法です。
この問題をいじっていると、述語を失うのは常に実行計画の「セグメント」ブロックであることに気付きました。min
これを確認するために、関数を使用したサブクエリの観点からクエリを再構成しました(ビューを参照D
)。そして出来上がり!- ビューに対する両方のクエリは、D
同一のプランを生成します。
ただし、悪いニュースは、この を使用したmin
トリックを使用できないことです。実際のセットアップでは、列Y
は実際には複数の列であるため、それらで注文することはできますが、それらを取得することはできませんmin()
。
したがって、2 番目の質問は次のようになります。最小限のサブクエリに似ているが、複数の列で機能するトリックを思い付くことができる人はいますか?
注 1 : テーブルには 2 つのレコードしかないため、これは確実に転換点とは関係ありません。
注 2 : ビューの存在とは関係ありません。view の例を参照してくださいC
。その場合、サーバーは喜んで seek を使用しています。