まず、はい、縮小は悪いです。 everは使用しないでください。わかります。残念ながら、これはSOPのようなものです。通常、メンテナンスウィンドウを取得してより多くのスペースを割り当て、インデックスを再構築/再編成できるようになるまでの一時的なギャップであるため、私は議論する立場にありません。
最近、従来のバックアップからサードパーティツールに切り替える問題がありました。データベースのサイズと最近削除したいくつかの大きなオブジェクトのため、カットオーバーの前に新しいツールでクリーンなバックアップをとる前に、データベースを縮小することは理にかなっています。少し予約がありましたが、めったに問題が発生しないので進めました。明らかに、ログをクリアすることは実際には問題ではありませんが、mdfを縮小していました。これにより、いくつかの大きなトランザクションの多いオブジェクトで多くのブロックが発生し、当然、これをどのように使用するかについてかなり深刻な質問がいくつか出されました。
私は多くの研究をしてきましたが、満足できるほどの詳細をまだ見つけていません。
SHRINKの動作の内部を実際に説明している場所はありますか?
他のオブジェクトよりも断片化されているオブジェクトを特定し、それがどのようにスペースを解放しているのかを判断する方法はありますか?または、テーブルがどの程度断片化されているかは問題ではなく、データベース内の他のオブジェクトと比較した場合のオブジェクトの全体的なサイズのほうが重要ですか?
ポール・ランドールはそれについて少し話します ここ 、しかしそれは十分な詳細ではありません。
Dmインデックスの統計に基づいて並べ替えることもできますが、サイズが大きく、インデックスが過剰であるため、一部の大規模データベースで実行するのはかなり困難です。それが私が心配する必要があるのはそれだけかどうかもわかりません。メインテーブルはヒープとして格納され、インデックスのみが実際に断片化されますが、異なるパーティションがどのように影響するのか、または基になるDBの他の部分も解放されるのかどうかはわかりません。
この質問 も見ましたが、私たちが探している粒度に構成できるかどうかはわかりません。
いくつかの考え:
1。 SHRINKDATABASE
は使用せず、常にSHRINKFILE
を使用してください。
あなたはそれがどのファイルからスペースを取っているのか、そしてどれだけ正確にどれだけのスペースを予約しておくのかを制御したいと考えています。次のようなクエリを実行して、各ファイルの実際の使用済み/空き容量を確認します。
SELECT DB_NAME() as dbname, type_desc, name as logical_name,
CONVERT(decimal(12,1),size/128.0) as TotalMB,
CONVERT(decimal(12,1),FILEPROPERTY(name,'SpaceUsed')/128.0) as UsedMB,
CONVERT(decimal(12,1),(size - FILEPROPERTY(name,'SpaceUsed'))/128.0) as FreeMB,
physical_name
FROM sys.database_files WITH (NOLOCK)
ORDER BY type, file_id;
プライマリデータファイルが100 GBであるが、実際に使用されるのは20 GBだけだとします。最終的なターゲットサイズを25 GBまたは30 GBにして、内部の空き領域を確保するとします。だからあなたは次のような縮小をするでしょう:
DBCC SHRINKFILE (name='logical_name', size=30000)
2。内部SHRINKFILE
動作
内部的には、データファイルを縮小すると、ファイルのendから使用済みのページが1つずつ移動され、ファイルの終わりに十分なスペースができるまで、最初の近くの空きスポットに移動しますあなたの目標サイズを満たすために。
これはかなり単純なブルートフォース方式であり、ページのコンテンツに注意を払わないため、テーブルの断片化が頻繁に発生します。 Paul Randalの記事 からリンク:
データファイルの縮小操作は、一度に1つのファイルに対して機能し、GAMビットマップを使用して、ファイルに割り当てられている最上位のページを見つけます。次に、それをファイルの先頭に向けて可能な限り移動します。
移動したいページが別のプロセスによってロックされている場合、ブロックされます。
3。 SHRINKSは進行状況を維持します
縮小を開始し、ブロックまたは他の競合するアクティビティのためにそれを停止する必要がある場合、それはその進捗状況を保持します。正常に移動したすべてのページは移動したままになります。後で再開して作業を完了することができます。
4。縮小の影響を受けるテーブルを見つける
sys.allocation_units
またはsys.partitions
でクエリを使用するか、おそらくDBCC PAGE
などを使用して、これを行ういくつかの方法があるかもしれませんが、私の推奨はdon気にしないでください。大規模なデータベースでは、データファイル全体に数千のオブジェクトが散在して残りますが、そのほとんどは気にしません。
しつこい場合は、検索で見つけた高度な記事を次に示します。
それがブロックし始めるとき、あなたはすでにどんなテーブル/インデックスが遊んでいるかを知ることができます、他のすべてはノイズです。
そのロックがクリアされずにページを移動する機会が与えられない場合は、他のアクティビティなしでダウンタイムをスケジュールする必要があるかもしれません。
5。完了したら、再インデックスを実行して断片化を修正します
データファイルは少し大きくなる可能性がありますが、データベースが1つの大きなテーブルでない限り、開始時よりも最終結果が小さいままになる可能性があります。
まず、DBCC SHRINKDATABASE
およびDBCC SHRINKFILE
。そうです、Paul Randallの記事ではDBCC SHRINKDATABASE
は、スペースを再利用しようとするファイルを決定します。ただし、ここで最も重要な点は、どのファイルを制御できないということです。 20 GBを再利用する必要があり、30 GBのログファイルと250 GBのデータファイルがある場合、ログファイルからその20 GBを再利用できます。これは、ほぼすぐに30 GBに戻る可能性があるため、縮小は完全に無駄です。時間の。ほとんどの場合、SQL Serverのエンジンが行うデータの通常のサイクルをよりよく理解できていると思います。 29 GB以上が無料の30 GBのログファイルと、30 GBが無料の250 GBのデータファイルがある場合、インデックスの再構築を行うときに、ログファイルが5 GBを超えるだけでよいかどうかをエンジンが把握している方がはるかに優れています。/reorg、またはデータロードプロセスに毎晩それが必要かどうか、および通常のデータアクティビティ(1か月に1GBの新しいデータなど)を参照しているかどうか、または20GBのデータをシステムにロードするかどうか数日。
そのうえ、 DBCC SHRINKDATABASE
は、データがどこに注意を払うつもりはありません。ほぼ完全なメインドライブに250 GBのデータファイルがあり、新しく作成した100 GBのファイルが新しいドライブにある場合、DBCC SHRINKDATBASE
は、スペースを解放する必要があるドライブが古いファイルである場合、少なくとも古いファイルではなく新しいファイルを圧縮する可能性が高くなります。
ここで、 Paulの記事doesは、ファイルがどのように縮小されるかを示します。データファイルとログファイルの両方が、ファイルの最後を切り取ることによって縮小されます。
ログファイルの場合、ファイルの末尾に切り捨てられる十分なスペースができるまで待つ必要があります。ログファイルは無限ループのように扱われます。それが最後に到達すると、最初から始まります。時間の経過とともに、ログの終わりは明確になり、最終的にスペースを解放できるようになります。
データファイルの場合、SQL Serverはファイルの最後が空になるまで辛抱強く待機するだけではありません。記事に記載されているように、縮小操作では、ファイルの末尾に最も近いページが検出され、ファイルの先頭にできるだけ近づいて移動され、ファイルの末尾に十分な空き領域ができるまでそれが繰り返されます。希望のサイズに縮小します。現在断片化されているものや、断片化されていないものは調べていません。その唯一の目的は、ファイルの最後にあるものを取り、それをできるだけ遠くに移動することです。
再び、ポールの例を見てください。彼には基本的に断片化のないテーブルがありました。すべてのページが移動されました。最後のページが最初になり、最初のページが最後になり、断片化は完全でした。
それは一種の移動のようなものです。すべての箱を梱包し、それらが属する部屋にラベルを付けます。ただし、引っ越し業者は読み書きができず、すべての箱をリビングルームに置きます。 「キッチン」ボックスの1つが暖炉のそばにあり、他のすべてのボックスの後ろにあります。他の人は「寝室」の箱や「家族の部屋」でくつろぐかもしれません。確かに、SQLの動作はそれよりも少し整理されていますが、論理的に移動するものをグループ化するのではなく、可能な限り移動するだけです。
これがお役に立てば幸いです。