web-dev-qa-db-ja.com

FREEPROCCACHEでtempdbを圧縮できるのはなぜですか?

誰かが愚かなことをし、tempdbのサイズが爆発しました。ドライブがいっぱいであるため、アラートが発生しています。私はそれを縮小しようとしました、そしてそれは縮小しませんでした(縮小クエリが彼らが働いたと言いましたが)。

Tempdb(SQL2014 SP1)には多くの空き領域があります。 tempdb>タスク>圧縮>ファイル>(解放できる空き容量を表示)

私は(SSMS 2016)縮小してより多くのスペースを残し、「最小サイズに縮小」します。しかし、ファイルは実際には縮小されません。

私はビジネスオーナーと協力して、サーバーが停止しているサーバー(sp_whoisactiveなど)を監視しています。

解決策を検索すると、 Tempdbを縮小しても縮小されない場合(brentozar.com)

以下を実行するとtempdbが機能し、元のサイズに戻ります。

 DBCC FREEPROCCACHE

 USE [tempdb]
 GO
 DBCC SHRINKFILE (N'tempdev' , 2048)
 GO

DBCC FREEPROCCACHE がすべてのキャッシュデータを解放し、プランに影響を与えることを理解しています。ただし、tempdbでスペースを使用している場合は、使用済みスペースとして表示され、通常の縮小には使用できません。

なぜこれはうまくいったのですか?

重要なのは、キャッシュされたオブジェクトがクエリプランに関連付けられていること、およびプロシージャキャッシュを解放することにより、それらのオブジェクトを削除してファイルを圧縮できることです。この質問を別の言い方で言いましょう。

Tempdbは、「最小のサイズに縮小」によって証明されるように、それを取り除けるスペースがあると考えています。消えないスペースは、実行されなくなった一時プロセスで作成されました。割り当てられた未使用の領域が大量にありますが、クエリプランを破棄せずに解放できないのはなぜですか?

クエリプランまたはキャッシュは、割り当てられたディスク領域に存在していませんが、縮小から保護されていますか?

アナロジー:「最小サイズに縮小」は、ガラスが半分満杯/空であることを示しますが、ガラスを壊さずに小さなガラスに移すことはできません内容のほとんどすべてを失う。


数年後、SQL 2014のインスタンスで同じ問題が発生し、緊急性が低下したため、実験を試す時間はありません。

クエリプランをなんとかして特定できた場合は、そのプランだけを削除して、ページの保持を解放してから、tempdbを圧縮できます。これを達成する方法を探していますが、まだ成功していません。

DBCC PAGE を使用して、そのページの内容を確認し、アドレスを指定できるでしょうか。

DBCC TRACEON (3604)  -- By default, the output is sent to the errorlog. If you want the output to come back to your current connection, turn on trace flag 3604.
GO
DBCC PAGE ([tempdb], 1, 1, 3); -- detailed dump of the PFS page
GO 

最後のページは937ですので、見ていきます。

DBCC PAGE ([tempdb], 1, 937, 3);
GO

そこに明確な問題は何もありません。最後の数ページは空白に見えます。

私は Mike Fields(2016年2月4日12:01 pm) によって提案を試しましたが、複数回試行しても1MBも解放されませんでした。

私は昨日この問題に遭遇し、SSMSタスクを使用してファイルを圧縮しても何も達成されなかったため、ファイルの圧縮に関するドキュメントを再度読み、これを試す必要があることに気付きました。

DBCC SHRINKFILE (N'tempdev' , NOTRUNCATE) -- Move allocated pages from end of file to top of file
DBCC SHRINKFILE (N'tempdev' , 0, TRUNCATEONLY) -- Drop unallocated pages from end of file

8つのtempdevファイルすべてに対してこれを実行しましたが、徐々に、やがてスペースの約80%が回復しました。他には何も機能しなかったので、私は本当にこれに驚きました。 1日15分ごとにジョブを実行する必要がありましたが、最終的にスペースが回復しました

SQL 2014インスタンスでは、クラスター化された列ストアインデックスを使用して大規模なデータベースが再構築されたときに、キャッシュを「自然に」クリアしました(nightly process)。前日は何もしない同じSHRINKFILEは、午前中に予想どおりに機能します。

USE [tempdb]
GO
DBCC SHRINKFILE (N'tempdev' , 2000)
GO

おそらく、クエリストアを使用して2016以降のインスタンスでオンデマンドで問題を再現できれば、何が起こっているのか正確に追跡する方が簡単でしょうか。

1
James Jenkins

この回答は、@ MrTCSが this link を指す質問の下のコメントと、@ KrisGruttemeyerがこの要約を使用したコメントに基づいています

TL; DR-「重要なのは、キャッシュされたオブジェクトがクエリプランに関連付けられていること、およびプロシージャキャッシュを解放することで、それらのオブジェクトを削除してファイルを圧縮できることです。」

私が理解しているように:

データファイルの最後のページに物理的に配置されたポインタ(または何か)があるため、tempdbを縮小できない場合の状況。 tempdbがいっぱいになるクエリプランを指します。クエリプランが存在する限り、そのページは解放されません。核となるオプションは、すべてのクエリプランをクリアするDBCC FREEPROCCACHEで、ページが解放されます。

0
James Jenkins