以下は Microsoft Docs の段落です。
DML操作の一部としてヒープに割り当てられた新しいページは、ヒープが再構築されるまでPAGE圧縮を使用しません。圧縮を削除して再適用するか、クラスター化インデックスを作成して削除して、ヒープを再構築します。
なぜそうなのか理解できません。指定した圧縮設定のヒープがある場合、それがテーブルに属するページに適用されないのはなぜですか?
ありがとう
違いの原因となる特定の内部メカニズムはわかりませんが、ヒープは(内部的に)クラスタ化インデックス(および場合によっては非クラスタ化インデックス)とは少し異なる方法で管理されていると言えます。
ヒープから行を削除して、1つ以上のデータページが空になる(行が割り当てられない)と、必ずしもその領域が解放されるわけではありません。おそらく、テーブルにクラスター化インデックスを作成してから削除するか、ALTER TABLE [TableName] REBUILD;
を呼び出す必要があります(SQL Server 2014以降)。詳細およびオプションについては、Microsoftドキュメントのページ [〜#〜] delete [〜#〜] を参照してください。
個々の行(つまり、セットベースのINSERT
ではない)をヒープに挿入しても、クラスター化インデックスの場合ほどデータページがいっぱいになりません。行(データと行オーバーヘッド)にスペースがあり、スロット配列の2バイトのオーバーヘッドがある限り、クラスター化インデックスは行に適合します。ただし、ヒープ内のデータページは、ページに残っているバイト数を使用せず、代わりにページがどの程度いっぱいであるかを示す非常に一般的なインジケーターを使用します。報告されるレベルはそれほど多くありません。レベルは次の線に沿ったものです:0%、20%、50%、80%、および100%フル。そして、別の行のためのスペースがまだある間に100%に切り替わります(実際、同じ数の行がセットベースの操作で挿入された場合、ページは可能な限りいっぱいになります)。もちろん、DELETE
操作と同様に、ヒープを再構築すると、データページに収まるだけの行がパックされます。
次に、Microsoft Docsページの「ページ圧縮が発生するとき」セクションから ページ圧縮実装 について取得した次の情報を検討します。
...最初のデータページにデータが追加されると、データは行圧縮されます。 ...ページがいっぱいになると、追加される次の行がページ圧縮操作を開始します。ページ全体が確認されます。 ...
したがって、データページが書き込まれる前に、クラスター化インデックスのALTER TABLE REBUILD、CREATE/DROP、またはデータ圧縮設定の変更(すべて再構築)が必要であるという、他のヒープ動作と完全に一致しているようです最適に。ヒープが(ページ全体)を完全に認識していない(ヒープが再構築されるまで)場合、ページがいつ完全に満杯かがわからない場合は、いつページ圧縮操作を開始するか(更新と単一行の挿入を処理するとき)がわかりません。
一部のヒープをページ圧縮の自動適用からさらに制限するもう1つの技術は(そうでない場合でも)、圧縮を適用すると、そのヒープ(存在する場合)のすべての非クラスター化インデックスを再構築する必要があることです。 「データ圧縮」のリンク先のページには、次のようにも記載されています。
ヒープの圧縮設定を変更するには、テーブルのすべての非クラスター化インデックスを再構築して、ヒープ内の新しい行の場所へのポインターを設定する必要があります。
参照されている「ポインター」は、行ID(RID)です。これは、FileID、PageID、およびページ上のスロット/位置の組み合わせです。これらのRIDは非クラスター化インデックスにコピーされます。正確な物理的な場所であるため、クラスター化インデックスキーを使用してBツリーをトラバースするよりもルックアップが高速になる場合があります。しかし、物理的な場所の1つの欠点は、場所が変わる可能性があることです。それがここでの問題です。ただし、クラスター化インデックスは、キー値がクラスター化インデックスへのポインターとして非クラスター化インデックスにコピーされるため、この問題の影響を受けません。また、キーの値は、物理的な場所が変わっても変わりません。
こちらもご覧ください:
ヒープ(クラスター化インデックスのないテーブル) のMicrosoftドキュメントページの「ヒープの管理」セクション:
ヒープを再構築して無駄なスペースを取り戻すには、ヒープ上にクラスター化インデックスを作成してから、そのクラスター化インデックスを削除します。
データ圧縮 のMicrosoftドキュメントページの「行とページの圧縮を使用する場合の考慮事項」セクション:
ヒープがページレベルの圧縮用に構成されている場合、ページは次の方法でのみページレベルの圧縮を受け取ります。
- データは一括最適化を有効にして一括インポートされます。
- データはINSERT INTO ... WITH(TABLOCK)構文を使用して挿入され、テーブルには非クラスター化インデックスがありません。
- PAGE圧縮オプションを指定してALTER TABLE ... REBUILDステートメントを実行すると、テーブルが再構築されます。
そして質問で引用された声明。
SQL Serverのすべてのメカニズムが本来あるべきものであるとは限りません。
Paul Randalは、この問題の管理について強力な推奨を提供しています。
http://www.sqlskills.com/blogs/paul/a-sql-server-dba-myth-a-day-2930-fixing-heap-fragmentation/