web-dev-qa-db-ja.com

ヒープ上の圧縮

以下は Microsoft Docs の段落です。

DML操作の一部としてヒープに割り当てられた新しいページは、ヒープが再構築されるまでPAGE圧縮を使用しません。圧縮を削除して再適用するか、クラスター化インデックスを作成して削除して、ヒープを再構築します。

なぜそうなのか理解できません。指定した圧縮設定のヒープがある場合、それがテーブルに属するページに適用されないのはなぜですか?

ありがとう

14
John Smith

違いの原因となる特定の内部メカニズムはわかりませんが、ヒープは(内部的に)クラスタ化インデックス(および場合によっては非クラスタ化インデックス)とは少し異なる方法で管理されていると言えます。

  • ヒープから行を削除して、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ステートメントを実行すると、テーブルが再構築されます。

    そして質問で引用された声明。

12
Solomon Rutzky

SQL Serverのすべてのメカニズムが本来あるべきものであるとは限りません。

Paul Randalは、この問題の管理について強力な推奨を提供しています。

http://www.sqlskills.com/blogs/paul/a-sql-server-dba-myth-a-day-2930-fixing-heap-fragmentation/

1
RLF