7

このフィドルを見てください: 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 を使用しています。

4

3 に答える 3

0

クエリは同等の出力を生成しますが、SQL オプティマイザーの目には異なります。この記事では、OPTION 句を確認することをお勧めしています (残念ながら、SQL 2005 より前には含まれていませんでした)。

Entity Framework の上に独自のクエリを作成できます。これは、目的のパフォーマンスを達成するための最善の策かもしれません。

于 2012-10-19T18:00:39.157 に答える
0

これが私自身の答えです。

最終的に、私はmin-powered トリックを使用し、Yそれらの列を一定長の文字列表現 (並べ替え用に慎重に調整) に変換し、それらの文字列を 1 つの文字列に結合することで、実際には複数の列であるという事実を回避しました。それが完了したら、その結合された文字列を の引数として使用できますmin()

私はまだこれを行う適切な方法を知りたいです。誰かがたまたまそれを知っていれば、私は感謝します。

于 2012-10-23T14:34:28.207 に答える