あなたが説明している動作は、多くの場合、不適切にキャッシュされたクエリ プランや古い統計が原因です。
WHERE 句に多数のパラメーターがある場合、特に次の形式のパラメーターの長いリストがある場合によく発生します。
(@parameter1 is NULL OR TableColumn1 = @parameter1)
たとえば、キャッシュされたクエリ プランの有効期限が切れ、proc が代表的でないパラメーター セットで呼び出されたとします。次に、このデータ プロファイルのプランがキャッシュされます。しかし、proc が非常に異なるパラメーターのセットで頻繁に共通している場合、その計画は適切ではない可能性があります。これは、「パラメータ スニッフィング」としてよく知られています。
この問題を軽減して解消する方法はありますが、トレードオフが伴い、SQL Server のバージョンに依存する場合があります。と を見てOPTIMIZE FOR
くださいOPTIMIZE FOR UNKNOWN
。IF (およびそれは大きな場合) proc が頻繁に呼び出されないが、できるだけ速く実行する必要がある場合OPTION(RECOMPILE)
は、呼び出されるたびに再コンパイルを強制するために、 としてマークすることができますが、頻繁に呼び出される procs または調査なしでこれを行わないでください。
[注: SQL Server 2008 ボックスに含まれるサービス パックと累積更新プログラム (CU)に注意してください。再コンパイルとパラメーター スニッフィング ロジックはバージョンによって異なる動作をします]
次のクエリ (Glenn Berry から) を実行して、統計の状態を確認します。
-- When were Statistics last updated on all indexes?
SELECT o.name, i.name AS [Index Name],
STATS_DATE(i.[object_id], i.index_id) AS [Statistics Date],
s.auto_created, s.no_recompute, s.user_created, st.row_count
FROM sys.objects AS o WITH (NOLOCK)
INNER JOIN sys.indexes AS i WITH (NOLOCK)
ON o.[object_id] = i.[object_id]
INNER JOIN sys.stats AS s WITH (NOLOCK)
ON i.[object_id] = s.[object_id]
AND i.index_id = s.stats_id
INNER JOIN sys.dm_db_partition_stats AS st WITH (NOLOCK)
ON o.[object_id] = st.[object_id]
AND i.[index_id] = st.[index_id]
WHERE o.[type] = 'U'
ORDER BY STATS_DATE(i.[object_id], i.index_id) ASC OPTION (RECOMPILE);