Azure SQL Databaseから不適切な実行プランを削除するにはどうすればよいですか?


12

DBCC FREEPROCCACHEAzure SQL DBでは機能しません。どうすれば、実稼働システムを傷つけないように計画を強制的にキャッシュから追い出すことができますか(つまり、テーブルを自由に変更することはできません)。これは特にEntity Frameworkによって作成されたSQL向けであるため、これらは自己管理型のストアドプロシージャではありません。事実上動的なSQLです。

(ソースは悪いインデックス->悪い統計などでした。それはすべて修正されましたが、悪い計画は消えません。)

更新: 彼が最初に到着したとき、@ mrdennyのソリューションを選択しました。ただし、@ Aaron Bertrandのスクリプトを使用して作業を正常に実行しています。みんな助けてくれてありがとう!!


Azureでsp_recompileを実行できますか?
mrdenny

はい。正確に何を実行しますか?ストアドプロシージャはありません。これはで実行される動的SQL sp_executesqlです。
Jaxidian

2
テーブル自体で実行でき、そのテーブルを使用するプランをフラッシュする必要があります。(これが機能する場合、私はそれを答えにします。)
mrdenny

1
テーブルでこれを試したところ、処理中にトランザクションでテーブルがロックされているようです。レコードが24個しかない10列のテーブルで試してみましたが、完了するまでに1分以上かかりました。この間、テーブルをクエリできませんでした。Productionの実際のテーブルでは、このようなことはできません!
Jaxidian

1
くそー、それは残念だ。nullを許可する列を追加するなど、スキーマを変更してからドロップする必要があるようです。これはキャッシュも消去するので、すぐに消えるはずです。テストで確実にわかります。
mrdenny

回答:


12

Azure SQL はこれを直接サポートするようになりました

Azure SQL Databaseは、ハッキングなしで現在のユーザーデータベースのprocキャッシュをクリアすることを直接サポートします。

ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;

追加情報

次のスクリプト(Shannon Gowen作)を使用して、プロセスを段階的に見ることができます。

-- run this script against a user database, not master
-- count number of plans currently in cache
select count(*) from sys.dm_exec_cached_plans;

-- Executing this statement will clear the procedure cache in the current database, which means that all queries will have to recompile.
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;

-- count number of plans in cache now, after they were cleared from cache
select count(*) from sys.dm_exec_cached_plans;

-- list available plans
select * from sys.dm_exec_cached_plans;

私はまだこれを試していませんが、これが実際に機能する場合、これはおそらく2017年の初めの時点での「最良の」回答です。これに感謝します。:
Jaxidian

私はこれを(プレミアムDBで)試しましたが、うまくいきました。
レミレマーチャンド

これを更新済みの「承認済み回答」としてフラグを立てましたが、まだ自分でテストしていません。私はこれをトッドとレミのフィードバックに直接基づいています。皆さんありがとう!
-Jaxidian

再訪するために、私はこれを使用しました。ここでトッドの答えにスクリプトをいくつか追加して、それを充実させていますが、彼の投稿は頭を悩ませています。
-Jaxidian

これは私にはうまくいかないようです-それは実行されますが、リストはまだいっぱいです-私はSQL Azureにいます-何が間違っている可能性がありますか?
ディルク・ボーア

12

今日これを行う明確な方法はありませんが、それは永続的なシナリオではありません(DBCCコマンドはまだサポートされていませんが、Query Storeで参照してください)。スキーマ変更のヒットが許容できる場合でも、悪いものだけでなく、基礎となるオブジェクトに関連するすべての計画が無効になるため、それは望んでいない場合があります。

これに対する信用は求めていませんが、動的SQLを構築して複数のテーブルに対して同じ操作を実行するのは非常に簡単です。

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER TABLE '
  + QUOTENAME(SCHEMA_NAME([schema_id])) 
  + '.' + QUOTENAME(name) + ' ADD fake_column INT NULL;
  ALTER TABLE ' 
  + QUOTENAME(SCHEMA_NAME([schema_id]))
  + '.' + QUOTENAME(name) + ' DROP COLUMN fake_column;'
FROM sys.tables
--WHERE name IN, LIKE, etc.

PRINT @sql;

-- if the command > 8K, you can see the second chunk e.g.

PRINT SUBSTRING(@sql, 8001, 8000);

--EXEC sys.sp_executesql @sql;

この「動的SQLの長さ」問題に関するヒントを書きまし ...)


私の場合、それらをすべて削除することは、悪いものをそこに残すよりもはるかに望ましいです。ヘッドアップをありがとう。私はあなたが特徴私を伝えることはできません知っているが、あなたは私を伝えることができないとき、あなたはもはやあなたがについて話すことができないものについて話については制限されることがありますか?;-)
Jaxidian

それも分類されています、ごめんなさい。:-)
アーロンバートランド

リンクの意味がわからない。私が意図したのは、nvarchar(max)変数が4000文字の後に制限に達することvarchar(max)です。その正確なスクリプトを実行します。〜450個のテーブルがあるため、簡単にヒットします(〜30/60個のテーブル)。varchar(max)は有効な構文であり、と同一でありvarchar(8000)、とnvarchar(max)同一ですnvarchar(4000)
Jaxidian

3
ええ、PRINTコマンドを実行すると、8000バイトしか表示されません。これはPRINTコマンドの制限であり、Azureではありません。コマンドを実行すると、全体を視覚的に検査できない場合でも機能します。
アーロンバートランド

... doh、ごめん、私はあなたが正しいと思う!私を修正してくれてありがとう!それはあなたの妻があなたが25分前に去ることを期待していたときに起こることです... ;-)このスクリプトは私にとって完璧に機能します!
Jaxidian

6

ヌル可能列を表に追加してから、列をドロップします。これにより、SQLはそのオブジェクトのキャッシュを強制的にフラッシュします。

すべてのテーブルを実行する場合、カーソルがトリックを実行する必要があります。「zzzzzz_go_away」などの表には決して存在しない列名を使用してください。


4

Azure SQL Databaseは現在サポートしていませんDBCC FREEPROCCACHE。そのため、キャッシュから実行プランを手動で削除することはできません。ただし、クエリ(ALTER TABLE/ ALTER VIEW)によって参照されるテーブルまたはビューに変更を加えると、プランはキャッシュから削除されます。(参照。)


あなたがここに投稿したものはすべて知っていました。これはストアドプロシージャでもビューでもないため、これらの1つを変更することはできません。負荷がかかり、ダウンタイムやテーブルのロックを引き起こさずに、これをトリガーするために、取るに足らない方法でテーブルを変更するにはどうすればよいですか?
-Jaxidian

1
ダミー列を追加してからドロップすることもできます。これにより、キャッシュからプランが削除されます。テーブルの大きさは?
キンシャー

@mrdennyが推奨するように、それが解決策になりました。助けてくれてありがとう!!:-)
Jaxidian

1
おかげで...わずか数秒は短い時間で... ... stackexchangeにいくつかの他のポストに答えるた
キン・シャー

1

すべての実行計画をクリアするには、これを使用します:

    SET NOCOUNT ON

DECLARE @lcl_name VARCHAR(100)
DECLARE @addcolumnSql nVARCHAR(MAX)
DECLARE @dropcolumnSql nVARCHAR(MAX)

DECLARE cur_name CURSOR FOR
SELECT name
FROM sysobjects
WHERE type = 'U'
OPEN cur_name
FETCH NEXT FROM cur_name INTO @lcl_name
WHILE @@Fetch_status = 0
BEGIN
set @addcolumnSql = 'alter table [' + @lcl_name + '] add temp_col_to_clear_exec_plan bit'
EXEcute sp_executesql @addcolumnSql
print @addcolumnSql
set @dropcolumnSql = 'alter table [' + @lcl_name + '] drop column temp_col_to_clear_exec_plan'
EXEcute sp_executesql @dropcolumnSql
print @dropcolumnSql
--  EXEC (@lcl_name )
FETCH NEXT FROM cur_name INTO @lcl_name
END
CLOSE cur_name
DEALLOCATE cur_name
SET NOCOUNT OFF

テーブルまたはそれを参照するビューを変更すると、実行計画はクリアされます。

ここでもう少し説明しますhttp://christianarg.wordpress.com/2013/08/22/remove-execution-plans-from-the-procedure-cache-in-sql-azure/

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.