現在、レガシーシステムへのデータインポートをいくつか行っていますが、このシステムが単一のクラスター化インデックスを使用していないことを発見しました。簡単なGoogle検索でHEAPテーブルの概念が紹介されましたが、クラスターテーブルよりもHEAPテーブルを優先する必要がある使用シナリオに興味がありますか?
私が理解している限り、HEAPテーブルは監査テーブルや、選択よりはるかに頻繁に挿入が行われる場合にのみ役立ちます。維持するクラスター化インデックスがないため、ディスク領域とディスクI/Oが節約され、読み取りが非常にまれであるため、追加の断片化が問題になることはありません。
唯一の有効な用途は
SELECT * INTO..
を使用した、テーブルの臨時の一時的および短期的なバックアップステージングテーブルは通常、非常にフラットで、使用前/使用後に切り捨てられます。
通常、クラスター化インデックスはデータサイズに比べて数個小さいです。データはインデックス構造の最低レベルです。
ヒープテーブルにも問題があります。少なくともこれら:
また見なさい
ヒープとクラスター化されたテーブルの1つの重要な利点に加えて、どちらの方法にも適用できる3番目の考慮事項があります。
ヒープは、間接的なレイヤーを節約します。インデックスには行IDが含まれており、ディスクの場所を直接(実際にはそうではなく、できるだけ直接)指します。したがって、ヒープに対するインデックスシークには、クラスター化されたテーブルに対する非クラスター化インデックスシークの約半分のコストがかかるはずです。
(ほとんど)空きインデックスのおかげで、クラスター化インデックス自体がソートされます。クラスタリングインデックスはデータの物理的な順序に反映されるため、実際のデータ自体の上に占めるスペースは比較的少なくて済みます。もちろん、とにかく保存する必要があります。物理的に順序付けられているため、このインデックスに対する範囲スキャンは、開始点までシークしてから、終了点まで非常に効率的に圧縮できます。
ヒープのインデックスは、64ビットのRIDを参照します。前述のように、クラスター化されたテーブルの非クラスター化インデックスは、クラスター化キーを参照します。クラスター化キーは、より小さい(32ビットINT
)、同じ(64ビットBIGINT
)、またはより大きな(48ビットのDATETIME2()
と32ビットのINT
、または128ビットのGUID)。明らかに、より広い参照は、より大きくてより高価なインデックスになります。
次の2つのテーブルを使用します。
CREATE TABLE TmpClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpClustered ADD CONSTRAINT PK_Tmp1 PRIMARY KEY CLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp1 ON TmpClustered (ID2)
CREATE TABLE TmpNonClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpNonClustered ADD CONSTRAINT PK_Tmp2 PRIMARY KEY NONCLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp2 ON TmpNonClustered (ID2)
...それぞれ8.7 Mのレコードが入力され、必要なスペースは両方のデータ用に150 MBでした。クラスタ化テーブルのインデックス用に120 MB、非クラスタ化テーブルのインデックス用に310 MB。これは、クラスター化インデックスがRIDよりも狭いこと、およびクラスター化インデックスがほとんどの場合「景品」であることを反映しています。 ID2
に一意のインデックスがない場合、非クラスター化テーブルに必要なインデックススペースは155 MBに低下しますが(予想どおり、半分)、150 [〜#〜] kb [〜# 〜]クラスター化されたPKの場合-ほとんど何もない。
したがって、32ビットインデックス(合計64ビット、名目上)を持つクラスター化テーブルの32ビットフィールドの非クラスター化インデックスは120 MBを要し、64ビットのヒープ内の32ビットフィールドのインデックスはRID(名目上、合計96ビット)は155 MBを要し、64ビットから96ビットのキーに変更することを単純に期待する50%の増加より少し少ないですが、当然、オーバーヘッドがあり、サイズの効果的な違いを減らします。
2つのテーブルの作成とインデックスの作成には、各テーブルで同じ時間がかかりました。スキャンまたはシークを含む簡単なテストを実行したところ、テーブル間に重要なパフォーマンスの違いは見つかりませんでした。この論文は、同時アクセスが非常に多い場合には大きな違いがあることを示しています。なぜそうなるのかはわかりません。できれば、大量の経験がある私よりも経験豊富な人OLTPシステムが教えてくれます。
〜40バイトのランダムな可変長データを追加しても、この等価性はそれほど変化しませんでした。 INT
sをワイドUUIDで置き換えることもできませんでした(各テーブルの速度はほぼ同じくらい遅くなりました)。あなたのマイレージは異なる場合がありますが、ほとんどの場合かどうかインデックスが利用可能であることがどのような種類よりも重要です。
テーブルがヒープであるか、インデックスがクラスタ化インデックスではないため、非クラスタ化インデックスに対して範囲スキャンを実行するには、インデックスをスキャンし、ヒットごとにテーブルに対してルックアップを実行する必要があります。これは非常に高価になる可能性があるため、テーブルをスキャンするだけの方が安くなる場合があります。ただし、カバーインデックスを使用してこれを回避できます。これは、テーブルをクラスター化したかどうかに関係なく適用されます。
@gbnが指摘したように、ヒープを圧縮する簡単な方法はありません。ただし、テーブルが時間の経過とともに徐々に増加する場合(非常に一般的なケース)、削除によって解放されたスペースは新しいデータで埋められるため、無駄はほとんどありません。
私が見たヒープとクラスター化されたテーブルの議論のいくつかは、インデックスのないヒープは常にテーブルスキャンを必要とするという点でクラスター化されたテーブルよりも劣っているという奇妙なストローマンの主張をしています。これは確かに本当ですが、より意味のある比較は、「インデックスが大きいクラスター化テーブル」と「インデックスが大きいヒープ」の比較です。テーブルが非常に小さい場合、または常にテーブルスキャンを実行する場合は、クラスタ化してもしなくてもかまいません。
クラスタ化されたテーブルの各インデックスはクラスタ化インデックスを参照するため、事実上すべてがインデックスをカバーしています。インデックス付けされた列とクラスタリング列を参照するクエリは、テーブルを検索せずにインデックススキャンを実行できます。クラスタリングインデックスが合成キーである場合、これは一般的に価値がありませんが、とにかく取得する必要があるビジネスキーである場合、これは素晴らしい機能です。
私はOLTPの専門家ではなく、データウェアハウジングを担当しています。ファクトテーブルの場合、ほとんどの場合、範囲スキャンが必要になる可能性が最も高いフィールド(通常は日付フィールド)でクラスタリングインデックスを使用します。ディメンションテーブルはPKでクラスター化されているため、ファクトテーブルに対するマージ結合用に事前に並べ替えられています。
クラスタリングインデックスを使用する理由はいくつかありますが、これらの理由のいずれも当てはまらない場合、オーバーヘッドは価値がない場合があります。クラスター化インデックスを普遍的に使用している人々の背後には、多くの「私たちは常にこのようにしてきた」と「それは単なるベストプラクティスです」と思われます。 your dataとyour loadの両方を試して、何が最適に機能するかを確認してください。
「唯一の有効な使用法は、インポート/エクスポート/ ETLプロセスで使用されるステージングテーブルの使用です」と言っても、控えめに言っても少し制限があります。特定のシステムの予想されるユースケースを採用し、ヒープまたはインデックス編成されたテーブルのメリットに基づいて選択する必要があります(私はOracleの用語を知っていますが、適切に説明しています)。
私たちのウェアハウスは、1日あたり約15億行をロードし、読み取りだけでなく、高度に並行した書き込みと処理をサポートする必要があります。リレーショナルストアはOLAPデータベースをサポートしているため、読み取りは主にテーブルスキャンになる傾向があります。一般的に、生成されるレポートとダウンストリームフィードは、インデックスが有用になるほど十分に選択的ではありません。システムはデータのスライディングウィンドウをサポートしているため、テーブルが読み込まれると、データを再度書き込むことはめったになく、パーティション分割、切り替え、マージにSch-Mロックを必要とするテーブルパーティション化の実装が不十分で、読み取りなどにSch-Sロックが必要です。パーティションテーブルもいくつかありますが、システムは多くのテーブルを使用する必要があり、多くのテーブルを使用することで、データのセグメント化とクリーンアップサイクルが容易になり、同時に競合も減少します。
そのため、任意の列でのインデックス構成テーブル(クラスター化テーブル)の追加オーバーヘッドと、ヒープへのbcp、OLAPパーティションの処理、テーブルスキャンクエリの実行が可能3日後にドロップすると、それだけの価値がないことを意味します。この場合、データは大規模なグリッドクラスターから返されるため、データの順序付けも行われないため、クラスター化インデックス付きのテーブルに挿入すると、 「ホットスポット」やページ分割などの他の問題。
また、ページが散らばっているという議論は少し不誠実だと思います。クラスタ化インデックスは、ファイル全体にページを分散させることもできます。インデックスを再作成した後(1000ページを超えると仮定)、ヒープよりも優れている可能性がありますが、インデックスの再作成も必要でした。
懸念がある場合は、スパース列と圧縮を使用してスペースを節約することもできます。場合によっては、クラスター化インデックスのあるテーブルを選択する方が高速になる可能性がありますが、それをロードして維持するために必要なリソースと比較検討する必要があります。
[編集]パーティション化されていないファクトテーブルのみがヒープであることを明確にする必要があります。パーティションテーブルとディメンションテーブルはすべて、効率的なルックアップなどをサポートするためにクラスター化インデックスを備えています。[編集2] 25億から15億に修正しました。ツタンカーメン、これらの2つの数字は隣り合っています。電話で応答を入力するとどうなりますか...