web-dev-qa-db-ja.com

クラスター化インデックスを追加/削除せずにSQLServerテーブルの断片化を減らしますか?

過去1年間ゆっくりと成長している大規模なデータベース(90GBデータ、70GBインデックス)があり、その成長/変更により、インデックスだけでなくテーブル自体の内部断片化が大量に発生しました。

(多数の)非常に断片化されたインデックスを解決するのは簡単です-断片化の程度に応じて、REORGANIZEまたはREBUILDがそれを処理します-しかし、実際のテーブルの断片化をクリーンアップする際に私が見つけることができる唯一のアドバイスは、クラスター化インデックスを追加することですテーブルに。今後、テーブルにクラスター化インデックスが必要ないため、すぐに削除しますが、クラスター化インデックスなしでこれを行う別の方法はありますか?これを行う「DBCC」コマンド?

ご協力いただきありがとうございます。

12
SqlRyan

問題

これは一般的な問題であり、SQL Serverを使用するすべての企業にとって深刻な問題であるため、少し明確にしましょう。

この問題、およびCREATE CLUSTEREDINDEXの必要性は誤解されています。

永続的なクラスター化インデックスを使用する方が、使用しないよりも優れていることに同意しました。しかし、それは重要ではなく、とにかく長い議論につながるので、それを脇に置いて、投稿された質問に焦点を当てましょう。

重要なのは、Heapにかなりの断片化があるということです。あなたはそれを「テーブル」と呼び続けますが、物理データストレージまたはDataStructureレベルではそのようなものはありません。テーブルは論理的な概念であり、物理的な概念ではありません。これは、物理的なDataStructuresのコレクションです。コレクションは、次の2つの可能性のうちの1つです。

  • ヒープ
    プラスすべての非クラスター化インデックス
    プラステキスト/画像チェーン

  • またはクラスター化インデックス
    (ヒープと one 非クラスター化インデックスを削除します)
    プラスすべての非クラスター化インデックス
    プラステキスト/画像チェーン。

ヒープはひどく断片化されます。散在する(ランダムな)挿入/削除/更新が多いほど、断片化が多くなります。

ヒープをそのままクリーンアップする方法はありません。 MSは機能を提供していません(他のベンダーは提供しています)。

解決

ただし、Create Clustered Indexは、ヒープを完全に書き換えて並べ替えることを知っています。したがって、(トリックではない)方法は、クラスター化インデックスを作成することですヒープのフラグメント化を解除する目的でのみ、後でドロップします。 table_size x1.25のデータベースに空き領域が必要です。

future の断片化を減らすために、必ずFILLFACTORを使用してください。その後、ヒープはより多くの割り当てスペースを使用し、更新による将来の挿入、削除、および行の拡張を可能にします。

注意

  1. 断片化には3つのレベルがあることに注意してください。これはレベルIIIのみを扱い、ヒープ内の断片化はクラスター化インデックスの欠如によって引き起こされます。

  2. 別のタスクとして、別のときに、永続的なクラスター化インデックスの実装を検討することもできます。これにより、断片化が完全に排除されます...ただし、これは投稿された問題とは別のものです。

コメントへの応答

SqlRyan:
これは私の問題に対する魔法の解決策にはなりませんが、私の問題はSQL Serverの制限の結果であり、クラスター化インデックスを追加することがヒープを「最適化」する唯一の方法であることは明らかです。

完全ではありません。私はそれを「制限」とは呼びません。

  1. ヒープ内の断片化を排除するために私が与えた方法は、クラスター化インデックスを作成し、そしてそれを削除することです。つまり。一時的に、その唯一の目的は断片化を修正することです。

  2. 全体フラグメンテーション(DataStructureは引き続きフラグメント化される可能性があります。以下のリンクの詳細情報を参照してください)が削減されるため、クラスター化インデックスをテーブルに(永続的に)実装する方がはるかに優れたソリューションです。ヒープで発生するフラグメンテーションよりもはるかに少ないです。

    • リレーショナルデータベース内のすべてのテーブル(「パイプ」または「キュー」テーブルを除く)には、さまざまな利点を活用するために、クラスター化インデックスが必要です。

    • クラスター化インデックスは、データを分散する列に配置する必要があり(INSERTの競合を回避)、レコードIDなどの単調に増加する列にインデックスを作成しないでください。 1、これは最後のページのINSERTホットスポットを保証します。

1.すべてのファイルのレコードIDは、単に便宜上SQLを使用して、「データベース」を非リレーショナルレコードファイリングシステムにします。このようなファイルには、リレーショナルデータベースの整合性、能力、速度はありません。

アンドリューヒル:
「3つのレベルの断片化があることに注意してください。これはレベルIIIのみを扱います」-他の2つの断片化レベルは何ですか?

MSSQLおよびSybaseASEには、3つのレベルのフラグメンテーションがあり、各レベル内にはいくつかの異なるタイプがあります。 Fragmentationを処理するときは、テーブルではなくDataStructuresに焦点を合わせる必要があることに注意してください(テーブルは、上記で説明したように、DataStructuresのコレクションです)。レベルは次のとおりです。

  • レベルI•Extra-DataStructure
    関連するDataStructureの外部、データベース全体またはデータベース内。

  • レベルII•DataStructure
    関連するDataStructure内で、ページの上(すべてのページにわたって)
    これは、DBAによって最も頻繁に対処されるレベルです。

  • レベルIII•ページ
    関連するDataStructure内、Pages内

これらのリンクは、断片化に関する完全な詳細を提供します。これらはSybaseASEに固有ですが、構造レベルでは、情報はMSSQLに適用されます。

私が与えた方法はレベルIIであり、レベルIIとIIIの断片化を修正することに注意してください。

32
PerformanceDBA

クラスター化インデックスを追加してテーブルの断片化を軽減し、すぐに削除すると述べています。

クラスター化インデックスは、クラスターキーで並べ替えることによって断片化を取り除きますが、このキーは将来使用できないと言います。これは疑問を投げかけます:なぜこのキーを使用してデフラグするのですか?

データをそのようにソートする必要があるのは明らかなので、このクラスター化されたキーを作成して保持することは理にかなっています。データの変更には、負担できないデータ移動のペナルティが発生するとおっしゃっています。デフォルト値よりも低いFILLFACTORでインデックスを作成することを考えましたか?データの変更パターンによっては、80%という低いものから利益を得ることができます。その場合、ページごとに20%の「未使用」スペースがありますが、クラスター化されたキー値が変更されると、ページ分割が少なくなるという利点があります。

それはあなたを助けることができますか?

1
sql_williamd

誰も話していない問題は、データの断片化ORハードドライブ自体のデバイスファイルのログ!!誰もがインデックスの断片化と、それを回避/制限する方法について話します断片化。

参考:データベースを作成するときは、.MDFの初期サイズと、データベースを拡張する必要があるときにどれだけ拡張するかを指定します。 .LDFファイルでも同じことを行います。 ISこれらの2つのファイルが大きくなると、必要な追加のディスクスペースに割り当てられたディスクスペースが、割り当てられた既存のディスクスペースと物理的に隣接するという保証はありません!!

これら2つのデバイスファイルのいずれかを拡張する必要があるたびに、ハードドライブのディスク領域が断片化する可能性があります。つまり、ハードドライブのヘッドは、データベース内の必要なデータにアクセスするために、ハードドライブのあるセクションから別のセクションに移動するために、よりハードに作業する必要があります(そしてより多くの時間がかかります)。それは、土地の小さな区画を購入し、その土地にぴったり合う家を建てることに似ています。家を拡張する必要があるとき、隣の空き地を購入しない限り、利用できる土地はありません。ただし、その間に誰かがすでにその土地を購入して家を建てた場合はどうでしょうか。その後、あなたはあなたの家を拡張することはできません。唯一の可能性は、「近所」に別の土地を購入し、その上に別の家を建てることです。問題は、あなたと2人の子供が家Aに住み、あなたの妻と3人目の子供が家Bに住むことになるということです。それは(あなたがまだ結婚している限り)苦痛です。

この状況を改善するための解決策は、「はるかに広い土地を購入し、既存の家(つまりデータベース)を取得し、それをより大きな土地に移動して、そこで家を拡張する」ことです。えーと、データベースでどうやってそれをするのですか?完全バックアップを実行し、データベースを削除し(万が一の場合に備えて、古い断片化されたデータベースと新しいデータベースの両方を保持するための十分な空きディスク容量がない場合)、十分な初期ディスク容量が割り当てられた新しいデータベースを作成します(オペレーティングシステムが、要求したスペースが連続していることを保証し、データベースを作成したばかりの新しいデータベーススペースに復元するという保証はありません。はい-それは面倒ですが、SQLデータベースファイルで動作する「自動ディスクデフラグツール」ソフトウェアを知りません。

0
TransParent57

DBCC SHRINKFILE with NOTRUNCATE。 を実行すると、ヒープをcompactできる可能性があります。

コメントに基づくと、永続的なクラスター化インデックスでテストしていないようです。

これを理解するために、すべてのテーブルにクラスター化インデックスを備えた1日あたり1,000万の新しい行を持つデータベースがあります。削除された「ギャップ」は、スケジュールされたALTER INDEX(およびフォワードポインター/ページ分割)を介して削除されます。

インデックス作成後、12GBのテーブルは2GBになる可能性があります。12GBが割り当てられているだけですが、非常に断片化されています。

0
gbn

レガシーデザインのデザインに制約されることに対するあなたの苦痛を理解しています。

問題のテーブルのバックアップを別のサーバーに復元し、クラスター化インデックスを作成する機会がありますか?狭い一意の列のセットまたはID列で作成された場合、クラスター化インデックスによってテーブル(データとインデックス)の合計サイズが減少する可能性があります。

私のレガシーアプリの1つでは、すべてのデータがビューを介してアクセスされていました。アプリケーションに影響を与えることなく、ID列とクラスター化インデックスを追加して、基になるテーブルのスキーマを変更することができました。

ヒープを持つことのもう1つの欠点は、転送された行に関連付けられた余分なIOです。

テーブルに永続的にクラストインデックスが必要であるという証拠があるかどうか尋ねられたとき、以下の記事が効果的であることがわかりました。

この記事はMicrosoftによるものです

0
RC_Cleland