web-dev-qa-db-ja.com

SQL Serverクエリキャッシュから特定の不良プランを削除するにはどうすればよいですか?

非常に悪いクエリプランを断続的にキャッシュする特定のSQL Server 2008クエリ(ストアドプロシージャではなく、同じSQL文字列-5分ごとに実行)があります。

このクエリは通常数ミリ秒で実行されますが、この不適切なクエリプランでは30秒以上かかります。

運用データベースサーバーのクエリキャッシュ全体を吹き飛ばすことなく、SQL Server 2008から外科的にキャッシュされたクエリプランを1つだけ削除するを削除するにはどうすればよいですか?

33
Jeff Atwood

私はいくつかのことを理解しました

select * from sys.dm_exec_query_stats

キャッシュされたすべてのクエリプランが表示されます。残念ながら、SQLテキストは表示されません。

ただし、SQLテキストを次のようにプランに結合できます。

select plan_handle, creation_time, last_execution_time, execution_count, qt.text
FROM 
   sys.dm_exec_query_stats qs
   CROSS APPLY sys.dm_exec_sql_text (qs.[sql_handle]) AS qt

ここから、WHERE句を追加して、クエリ内にあることがわかっているSQLを検索し、実行することができます。

DBCC FREEPROCCACHE (plan_handle_id_goes_here)

クエリプランキャッシュから各クエリプランを削除します。簡単でも便利でもありませんが、動作する表示.

編集:entireクエリキャッシュのダンプも機能し、少なくとも私の経験では、思ったより危険が少ないです:

DBCC FREESYSTEMCACHE ('ALL') WITH MARK_IN_USE_FOR_REMOVAL;
39
Jeff Atwood

適切なプランがどのように見えるかがわかっている場合は、 プランのヒント を使用してください。

特定のキャッシュエントリを削除することはできませんが、キャッシュプール全体を DBCC FREESYSTEMCACHE(cachename/poolname) でクリーンアップできます。

実行中に問題が発生したsession_idのプランハンドルがある場合( sys.dm_exec_requests.plan_handle から、または sys.dm_exec_query_stats から)、不正なクエリプランのキャッシュ名を取得できます。 =実行後):

_select ce.name
from sys.dm_exec_cached_plans cp
join sys.dm_os_memory_cache_entries ce on cp.memory_object_address = ce.memory_object_address
where cp.plan_handle = @bad_plan
_

ただし、すべてのSQLプランには「SQLプラン」という名前が付いているため、DBCC FREESYSTEMCACHEに適したプランを選択することは困難です。

更新

気にしないでください、DBCC FREEPROCCACHE(plan_handle)を忘れてしまいました。

6
Remus Rusanu

[〜#〜] freeproccache [〜#〜]ソリューションは問題ありませんが、これを行うより直接的な方法は、SQL文字列でOPTION(RECOMPILE)を使用することです( SPではなかったとお伝えしました)、これはエンジンにシングルユースプランを伝えます。これは、パラメータースニッフィングがあると思われるか、統計情報が実行ごとに大幅に異なり、キャッシュプランの問題が疑われるためです。

DECLARE @SQL NVARCHAR(4000)
SELECT @SQL = 'SELECT * FROM Table WHERE Column LIKE @NAME OPTION (RECOMPILE)'
EXEC sp_executesql @SQL, N'@NAME varchar(15)', 'MyName' 
1
CodeCowboyOrg