SQL ServerでHEAPフラグメンテーションを下げる方法は?


10

私は最近、1つのヒープテーブルに70%以上の断片化があることがわかりました。だから私はすることにしました

ALTER TABLE dbo.myTable REBUILD

面白いことに、その後20%の断片化がありました。それ以来、そのテーブルへの書き込みはありませんでした。だから私はもう一度リビルドをすることにしました。

2回目以降は、テーブルハットの断片化が50%増えるため、さらに多くのことを実現できます。 どうしてこんなことが起こるのか本当にわかりません...


論理的な断片化とはどういう意味ですか。これは、データページの使用に関する断片化です。順序はありませんが、順序付けされていないデータ自体は断片化されていません。この場合の断片化は、データページの効率的な使用を意味します。
tuxmania

2
テーブルはどれくらい大きいですか?行とページ。
Cody Konior

回答:


17

ヒープ内での断片化の意味

DMV avg_fragmentation_in_percentをクエリして列から取得するヒープの断片化値sys.dm_db_index_physical_statsは、

インデックスの論理断片化、またはIN_ROW_DATAアロケーションユニットのヒープのエクステント断片化

さらに、同じBOLは、

これは、ヒープのリーフページ内の順不同のエクステントの割合です。順不同エクステントとは、ヒープの現在のページを含むエクステントが、前のページを含むエクステントの次のエクステントと物理的に異なるエクステントです。

あなたはそれが見ることができるようにヒープに割り当てられたページ内の空き領域の存在ではないが、ページの様々な一連の断片化を作成します。

これは小さなテストで実証できます。ヒープテーブルを作成し、レコードをいくつか挿入してから、断片化をチェックします。

create table dbo.HeapTest
(
Id INT not NULL Default (1),
Col1   char(5000) Not null Default ('Heaps Are Cool')
)

SET NOCOUNT ON

Insert into dbo.Heaptest default values
go 50

select index_type_desc,avg_fragmentation_in_percent,fragment_count,
avg_page_space_used_in_percent,record_count
from sys.dm_db_index_physical_stats(db_id(),object_id('dbo.HeapTest','U'),0,default,'detailed')

したがって、ヒープテーブルは50レコードで作成されます。以下は、クエリDMV sys.dm_db_index_physical statsの後の断片化の様子です。

ここに画像の説明を入力してください

avg_fragmentation_in_percent列の値が33%であることがわかります。次に、ページがどのように配置されているかを見てみましょう。これは、文書化されていないクエリを使用して行うことができます%%lockres%%。クエリは

SELECT  %%lockres%%, * FROM dbo.HeapTest;

そして、出力は次のようになります。該当する部分のみを添付します。dbo.HeapTestテーブルに50行を挿入したため、クエリは50行を生成しました。

ここに画像の説明を入力してください

最初のページにはIDがあり197、次のページにはIDがあります。242後続のページには、ページIDに到達するまで継続的なID 264があります280。したがって、ページID番号のこのジャンプが、実際に断片化を引き起こしています。

次に、ヒープを再構築してコマンドを再度実行して、断片化とページの配置を確認します。次のような断片化が発生します

ここに画像の説明を入力してください

断片化が今であることがわかります14%

割り当てられたページ番号を見てみましょう

ここに画像の説明を入力してください

ジャンプレストは1つだけで、すべてのページにシリアルにページIDが割り当てられます。ジャンプが1つしかないため、断片化が大幅に減少しました。

ヒープを再構築しましたが、断片化をチェックすると完全になくなりました。そしてページIDの割り当ては

ここに画像の説明を入力してください

断片化が増加した理由

これで、断片化が発生する原因について確認できます。ページがヒープに割り当てられているとき、ページが連続的ではないことを裏付けることができます。上記のように、断片化の値が増加する原因は、ページに割り当てられているPAGE IDのジャンプでした。

頭の後ろで、HEAPのフラグメント化という言葉には意味がないことにも注意してください。順序付けされていない一連のページのフラグメント化をどのように定義しますか。

断片化が本当に心配

ヒープテーブルが断片化し、クエリが遅くなるシナリオに本当に直面している場合は、テーブルを再構築するよりもテーブルにクラスター化インデックスを作成する方が適切です。理由は、ヒープを再構築すると、基になる非クラスター化インデックスもすべて再構築されるため、再構築プロセスに非常に長い時間がかかり、多くのリソースを利用し、トランザクションログが膨らむためです。本番システムでは、常にこれを回避しようとします。パウロはこれについて、ヒープに関する神話のセクションで取り上げました。

PS:本番システムでは、文書化されていないコマンドを使用しないでください。これはデモ用です。


詳細な分析ありがとうございます。一部のデータボールト愛好家はクラスター化インデックスを使用するよりも優れていると考えているが、ヒープに多くのチェック制約と非クラスター化インデックスを使用しているため、このような状況でのヒープの利点は実際にはわかりません。しかし、私は愚かな開発者だけなので、これに対処する必要があります。洞察をありがとう:)
tuxmania '21

selectを実行するにはどうすればいいですか? 1つのテーブル?'object_id'にテーブル名を正しく指定した場合でも、すべてのテーブルのすべてのインデックスで返されます
Mickael

@Mickael現在のデータベースを取得する関数db_id()を使用し、オブジェクト名を具体的に指定したので、これは常に現在のデータベースを調べHeaptest、結果を探して提供します。きっと何かを見逃しているかもしれません。その場合、互換性レベルが80でないことを確認して
ください。db_id

@Shanky文書化されていないクエリ%% lockres %%を本番環境で使用することをお勧めしませんか?詳しく説明していただけますか?
ラルフ

@ user1624552文書化されていないというだけの理由で、MSはそれに関する文書も更新していません。それがどのように機能するかという後遺症は何ですか?どこにも文書化されていません。例隠しスケジューラを作成するコマンドfn_dump_dblog()があり、それは良くありません。このコマンドもサポートされていません。あなたはそれを使うことができますが、リスクはあなたにあります。
シャンキー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.