0

データベースには、2 つの大きなテーブルを検索して値が存在するかどうかを確認する関数があります。これはかなり大きなクエリですが、インデックスを使用するように最適化されており、通常はかなり高速に実行されます。

過去 2 週間で 3 回、この関数は混乱して実行速度が極端に遅くなり、デッドロックやパフォーマンスの低下を引き起こしました。これは、使用量がピークに達していないときでも発生します。

SQL Server で「Alter Function」を使用して関数を再構築すると、問題が解決するようです。これを行うと、サーバーの使用は通常に戻り、すべて問題ありません。

これにより、関数のクエリ プランが再構築され、正しいインデックスが考慮されていると考えられますが、SQL Server がクエリ プランを突然悪いプランに変更した理由はわかりません。

この動作を引き起こす可能性のあるもの、またはそれをテストまたは防止する方法を知っている人はいますか? SQL Server 2008 Enterprise を実行しています。

4

1 に答える 1

5

あなたが説明している動作は、多くの場合、不適切にキャッシュされたクエリ プランや古い統計が原因です。

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); 
于 2011-01-29T00:31:43.947 に答える