6

where 句で値を指定すると、高速 (< 1 秒) に実行されるビューがあります。

SELECT *
FROM vwPayments
WHERE AccountId = 8155

最初のクエリの実行計画

...しかし、その値が変数の場合、実行は遅くなります (~3 秒):

DECLARE @AccountId BIGINT = 8155

SELECT *
FROM vwPayments
WHERE AccountId = @AccountId

2 番目のクエリの実行計画

2 番目のクエリの実行計画が異なるのはなぜですか? なぜこんなに遅いのですか?

4

5 に答える 5

4

最初のケースでは、ステートメントのコンパイル中にパラメーター値が既知でした。オプティマイザーは、統計ヒストグラムを使用して、その特定のパラメーター値に最適な計画を生成しました。

ローカル変数を定義したとき、SQL サーバーはパラメーター値を使用して「最適な値」を見つけることができませんでした。パラメーター値はコンパイル時には不明であるため、オプティマイザーは「一様分布」に基づいて推定行数を計算します。オプティマイザは、考えられる入力パラメータ値に対して「十分」な計画を思いつきました。

あなたのケースをほぼ正確に説明している別の興味深い記事は、ここにあります。

于 2013-06-11T03:00:04.020 に答える
2

つまり、クエリ オプティマイザーが最適なプランを選択するために使用する統計分析では、値が既知の値の場合はシークを選択し、値が不明な場合は統計とスキャンを利用できます。where 句の値が判明する前にプランがコンパイルされるため、2 番目の選択肢でスキャンが選択されます。

この特定のケースでは、クエリ アナライザーを使い回すことをお勧めすることはめったにありませんが、forceseekヒントやその他のクエリ ヒントを使用してエンジンをオーバーライドすることができます。ただし、エンジンの助けを借りて最適な計画を取得する方法を見つけることは、はるかに優れたソリューションであることに注意してください。

Google で簡単に検索したところ、クエリ プランにさらに深く影響を与えるローカル変数の概念について説明している適切な記事を見つけました。

于 2013-06-10T22:13:49.920 に答える
0

パラメータのスニッフィングである可能性があります。次のことを試してみてください-ストアドプロシージャにあると思いますか?

 
DECLARE @Local_AccountId BIGINT = @AccountId

選択する *
から vwPayments
WHERE AccountId = @Local_AccountId

パラメータ スニッフィングの詳細については、次のリンクを参照してください: http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx

結果が異なるかどうかを確認します。この問題に何度か遭遇しました。特に、クエリがピーク時に頻繁に呼び出され、キャッシュされた実行プランがオフピーク時に作成されたものである場合です。

別のオプションですが、プロシージャ定義に「WITH RECOMPILE」を追加する必要はありません。これにより、呼び出されるたびにプロシージャが再コンパイルされます。http://www.techrepublic.com/article/understanding-sql-servers-with-recompile-option/5662581 を表示

于 2013-06-10T22:13:26.203 に答える