テーブルにクラスター化インデックスがある場合、インデックスはテーブルデータです(それ以外の場合は、ヒープタイプのテーブルがあります)。クラスタ化インデックス(実際には任意のインデックスですが、非クラスタ化インデックスの「データ」としてカウントされない)を再構築すると、部分的に使用されているページがより完全な形式にマージされます。
データをインデックス(クラスター化またはその他)でインデックスに挿入すると、必要に応じてリーフページが作成され、ページの最後の部分ページが1つだけになります。インデックス順にデータを入力するとき、データが適切な場所に収まるようにページを分割する必要があります。最終的に、約半分のページが2ページになり、新しい行がその1ページに入ります。時間の経過とともにこれが頻繁に発生し、かなりの量の余分なスペースが消費されますが、将来の挿入によってある程度のギャップが埋められます。非リーフページでも同様の効果が見られますが、実際のデータページの方がはるかに重要です。
また、削除するとページが部分的になる場合があります。ページ内のすべての行を削除すると、「未使用」としてカウントされますが、1つ以上のデータ行が残っている場合でも、使用中としてカウントされます。1ページに10バイトを使用する行が1つしかない場合でも、そのページは、使用されているスペースの数で8192バイトとしてカウントされます。繰り返しになりますが、将来の挿入によってギャップが埋められる可能性があります。
可変長の行の場合、更新によって同じ効果が得られる場合もあります。行が小さくなると、ページにスペースが残り、後で再利用するのが難しくなる可能性があります。ほぼ完全なページの行が長くなると、ページ分割が強制される可能性があります。 。
SQL Serverは、インデックスの再構築順序などが明示的に指示されるまで、ページの使用方法を再調整してデータを正規化しようとする時間を費やしません。そのようなガベージコレクションの演習はパフォーマンスの悪夢になる可能性があります。
これはあなたが見ているものだと思いますが、データが絶対に必要とする量の〜2.7倍に十分なスペースが割り当てられていることは、特に悪いケースだと思います。インデックス内の重要なキーの1つ(おそらくUUID列)としてランダムなものがあることを意味している可能性があります。つまり、新しい行がインデックス順に追加されることはほとんどありません。また、最近かなりの数の削除が発生しました。
ページ分割の例
4つがページに収まる固定長の行をインデックス順に挿入します。
Start with one empty page:
[__|__|__|__]
Add the first item in index order:
[00|__|__|__]
Add the next three
[00|02|04|06]
Adding the next will result in a new page:
[00|02|04|06] [08|__|__|__]
And so on...
[00|02|04|06] [08|10|12|14] [16|18|__|__]
ここで、インデックス順以外の行を追加します(これが上記の偶数のみを使用した理由です):追加する11
と、2番目のページが拡張され(固定サイズのため不可能)、11を超えるものをすべて1つ上に移動します(コストが高すぎる)大きなインデックス)または次のようにページを分割:
[00|02|04|06] [08|10|11|__] [12|14|__|__] [16|18|__|__]
ここから追加する13
と、17
現在は関連ページに余裕があるため、分割は行われません。
[00|02|04|06] [08|10|11|__] [12|13|14|__] [16|17|18|__]
03を追加すると、次のようになります。
[00|02|03|__] [04|06|__|__] [08|10|11|__] [12|13|14|__] [16|17|18|__]
ご覧のとおり、これらの挿入操作の後、現在5行のデータページが割り当てられており、合計20行に相当しますが、そこには14行しかありません(スペースの30%を「無駄にしています」)。
デフォルトのオプション(「FILL FACTOR」については以下を参照)で再構築すると、次のようになります。
[00|02|03|04] [06|08|10|11] [12|13|14|16] [17|18|__|__]
この簡単な例では、1ページを保存しています。削除がインデックスの順序が正しくない挿入と同様の効果を持つ方法を簡単に確認できます。
緩和
データがインデックスの順序に対してかなりランダムな順序になると予想している場合はFILLFACTOR
、インデックスを作成または再構築するときにこのオプションを使用して、SQL Serverにギャップを人為的に残して後で埋めるように指示できます-長期的にはページ分割を減らしますが、最初はより多くのスペースを取ります。もちろん、この値を間違って取得すると、状況を改善するのではなく、事態をさらに悪化させる可能性があるため、注意して処理してください。
特にクラスター化インデックスでのページ分割は、挿入/更新のパフォーマンスに影響を与える可能性があるFILLFACTOR
ため、書き込みアクティビティが多いデータベースでのスペース使用の問題ではなく、そのために微調整される場合があります(ただし、ほとんどのアプリでは、読み取りが書き込みよりも多い数桁の大きさで、実質的にランダムなコンテンツを持つ列にインデックスがある場合などの特定の場合を除いて、通常はfill-factorを100%のままにした方がよいでしょう。
他のビッグネームDBにも同様のオプションがあると思いますが、このレベルの制御も必要です。
更新
ALTER INDEX
上記の入力を開始した後に質問に追加されたステートメントについて:インデックスが最初に構築されたとき(または最後に再構築されたとき)のオプションは同じであると想定していますが、そうでない場合、これを追加すると圧縮オプションが非常に重要になる可能性があります周りの時間。また、そのステートメントでは、fillfactorが100%ではなく85%に設定されているため、再構築後すぐに各リーフページは約15%空になります。