web-dev-qa-db-ja.com

インデックスの断片化-結果を正しく解釈していますか?

私はDBAではありませんが、現在数百のテーブルと最大5 TBのデータを保持するデータベースを担当しています。私は最近、インデックスの断片化を判別するために、次のクエリを実行しました。

Declare @DatabaseId Int = DB_ID('ODS')

SELECT 
    OBJECT_NAME(T.OBJECT_ID) as TableName, 
    T2.Name as IndexName,
    T.index_id as IndexId,
    index_type_desc as IndexType,
    index_level as IndexLevel,
    avg_fragmentation_in_percent as AverageFragmentationPercent,
    avg_page_space_used_in_percent as AveragePageSpaceUsedPercent,
    page_count as PageCount
FROM sys.dm_db_index_physical_stats (@DatabaseId, NULL, NULL, NULL, 'DETAILED') T
    INNER JOIN [sys].[indexes] T2 ON T.index_id = T2.index_id And T.object_id = T2.object_id
ORDER BY avg_fragmentation_in_percent DESC

結果セットの最初の30〜40行は次のようになります(Excelにインポートした後)。

enter image description here

これは私にとって非常に驚くべきことでした。私はこれを正しく読んでいますか、100%断片化されているこれらのすべてのインデックス、実際にはもっと多くのインデックスがあるのですか?私のクエリは正しいですか?

6
Randy Minder

そのはっきりと見えるpage_count添付した図に示されているすべてのインデックスの<1500です。このような場合、インデックスが100%に断片化されていても、これは[〜#〜]ではありません[〜#〜]パフォーマンスの問題が発生します。

実際には、以下をお読みになった場合のMicrosoftからの断片化に関する推奨事項 BOL 2000バージョン

断片化はディスクI/Oに影響します。したがって、ページがSQL Serverによってキャッシュされる可能性が低いため、大きなインデックスに焦点を当てます。 DBCC SHOWCONTIGによって報告されたページ数を使用して、インデックスのサイズ(各ページのサイズは8 KB)を把握します。一般に、1,000ページ未満のインデックスの断片化レベルを気にする必要はありません。テストでは、10,000ページを超えるインデックスがパフォーマンスの向上を実現し、大幅に多いページ(50,000ページを超える)のインデックスで最大の向上が得られました。

以下は、古い接続項目(古い接続項目は廃止され、バグと機能のリクエストは削除されませんでした)に関するMicrosoftチームからの返信です。これは、再構築後も断片化が減少しない理由を理解するために提起されました。

小さなテーブルの場合、通常、断片化に対するパフォーマンスへの影響は検出できません。最初の8ページの割り当ては混合エクステントからのものであり、混合エクステントはデータベースファイルのどこにでも配置できます。インデックスを再構築しても、この性質は変わりません。小さなテーブルがある場合、これらの混合ページは断片化の計算中に非常に重くなります。したがって、インデックスを再構築しても断片化は減らない可能性があります。 (実際のところ、再構築後に断片化が増加するケースを簡単に構築することができます。)これらの断片化は、クエリのパフォーマンスにとって問題にはなりません。だから基本的には無視できます。

以下のクエリを使用する必要があります。これにより、page_count <1500の不要なインデックスが除外されます。 page_count> 1500のインデックスのみを再構築することをお勧めします

Declare @DatabaseId Int = DB_ID('ODS')

SELECT 
    OBJECT_NAME(T.OBJECT_ID) as TableName, 
    T2.Name as IndexName,
    T.index_id as IndexId,
    index_type_desc as IndexType,
    index_level as IndexLevel,
    avg_fragmentation_in_percent as AverageFragmentationPercent,
    avg_page_space_used_in_percent as AveragePageSpaceUsedPercent,
    page_count as PageCount
FROM sys.dm_db_index_physical_stats (@DatabaseId, NULL, NULL, NULL, 'DETAILED') T
    INNER JOIN [sys].[indexes] T2 ON T.index_id = T2.index_id And T.object_id = T2.object_id
where page_count >1500--this would filter out irrelevant index frag.
ORDER BY avg_fragmentation_in_percent DESC

[〜#〜]ノート[〜#〜]1500 figure推奨事項は、Microsoftがハードで高速なルールとして推奨しているものではなく、広く受け入れられている数値です。一部のフォーラムでは、1000の値を使用している人々を目にします。コアポイントは、インデックスのpage_countがかなり少ない場合、そのようなインデックスは実際にパフォーマンスの問題を引き起こさないため、そのインデックスを再構築または再編成しないことです。

10
Shanky

はい、それはそれがどのように見えるかです。 Excelに移動した後、データにエラーが発生していない限り。

ただし、これらはすべて非常に小さなテーブルです。たとえば、1,000ページ未満のテーブルの断片化を気にする必要はありません。*それでも、次のオーダーまたは2桁になるまであまり気にする必要はありません。断片化してもメモリ。

それらを再編成するために費やす作業は、期待した影響を与えません。また、実際に目にする変更から得られるメリットは、一時的にそれを正当化するものではありません。このような小さなテーブルは、最初からクエリから除外するだけです。

*1,000ページは単なる私の球場です。あなたが知っているものから数えてください。これにはマジックナンバーはありません。ただし、小さなテーブルでは、真剣に、他の場所に努力を集中してください。

10
Aaron Bertrand