HEAPテーブルの有効な使用シナリオは何ですか?


31

現在、いくつかのデータをレガシシステムにインポートしていますが、このシステムが単一のクラスター化インデックスを使用していないことがわかりました。簡単なGoogle検索でHEAPテーブルの概念を紹介しましたが、クラスター化されたテーブルよりもHEAPテーブルを優先する使用シナリオを知りたいのですが。

私が理解している限り、HEAPテーブルは監査テーブルおよび/または挿入が選択よりもはるかに頻繁に発生する場合にのみ役立ちます。維持するクラスター化インデックスがないため、ディスク領域とディスクI / Oが節約され、非常にまれな読み取りのため、追加の断片化は問題になりません。


1
SQL Serverについて話しているのですか?
-a_horse_with_no_name

はい@a_horse_with_no_name、私はSRYを言及するのを忘れてしまった
marc.d

ヒープテーブルは、ユーザーが大量にヒットする数百万行のテーブルに適しています。欠点は、データがソートされずに物理的に保存されるため、多くのスペースを占有できることです。また、クエリに合わせてインデックスを調整します。パフォーマンスの問題のため、クラスター化インデックスをまったく使用しない場所で作業しました。おそらくクラスター化インデックスの選択肢が貧弱なためですが、ヒープテーブルを使用するだけであれば、心配する必要はありません。より良い解決策は、SQL Serverのエンタープライズ版を使用して、大きなテーブルを水平方向にパーティション分割することです。しかし、


回答:


22

有効な用途は

  • インポート/エクスポート/ ETLプロセスで使用されるステージングテーブル。
  • を使用したテーブルのアドホック、一時および短期バックアップ SELECT * INTO..

通常、ステージングテーブルは非常にフラットで、使用前/使用後に切り捨てられます。

通常、クラスター化インデックスはデータサイズに比べてわずかであることに注意してください。データインデックス構造の最下位レベルです。

ヒープテーブルにも問題があります。少なくともこれら:

こちらもご覧ください


2
通常は、2つの別々のことにヒープを使用します。セットが大きすぎて一時テーブルが効果的に機能しない場合に、一時的にデータを保存するために使用するETLステージングおよび作業テーブル。これらはすべて、次回のロード時に切り捨てられます。
ゼーン

ところで、いい質問です。
ゼーン

1
ちょっとした微調整-変更を行う前に小さなテーブルのクイックバックアップを作成するためにSELECT INTOを実行すると、デフォルトでヒープが作成されます。私はそれが有効な使用であると言うだろう-しかし、それはただつまらないものだ。自分の作業が完了したとわかったらすぐに、そのヒープを取り除きたいと思います。
ブレントオザー

@BrentOzar:同意します、私はいつも自分でやります。私の答えの精神は「長期的かつ永続的なテーブル」ですが、更新します
-gbn

9

主な考慮事項

ヒープとクラスタ化されたテーブルの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(予想どおり半分)に低下しますが、クラスタ化PK ではわずか150 KBになり、ほとんどゼロになります。

したがって、32ビットインデックス(合計で64ビット、名目上)のクラスター化テーブル内の32ビットフィールドの非クラスター化インデックスは120 MBを必要とし、64ビットのヒープ内の32ビットフィールドのインデックスはRID(合計96ビット、名目上)は155 MBで、64ビットキーから96ビットキーへの移行が単純に予想される50%の増加より少し少ないですが、もちろん、オーバーヘッドがあり、サイズの効果的な差が小さくなります。

2つのテーブルにデータを取り込み、インデックスを作成するには、各テーブルで同じ時間がかかりました。スキャンまたはシークを含む簡単なテストを実行したところ、テーブル間に重要なパフォーマンスの違いは見られませんでした。この論文は、高度な同時アクセスの場合に大きな違いを示しています。なぜそれが起こるのかはわかりませんが、できれば、大量のOLTPシステムを使用している私よりも経験のある人が教えてくれることを願っています。

ランダム可変長データを40バイトまで追加しても、この等価性はそれほど変わりませんでした。INTsをワイドUUIDに置き換えることもしませんでした(各テーブルはほぼ同じ程度に遅くなりました)。走行距離は異なる場合がありますが、ほとんどの場合、どの種類よりもインデックスが利用可能かどうかが重要です。

小片

テーブルがヒープであるか、インデックスがクラスター化インデックスではないため、非クラスター化インデックスに対して範囲スキャンを実行するには、インデックスをスキャンしてから、ヒットごとにテーブルを検索します。これは非常に高価になる可能性があるため、テーブルをスキャンする方が安価な場合があります。ただし、カバリングインデックスを使用してこの問題を回避できます。これは、テーブルをクラスター化したかどうかに関係なく適用されます。

@gbnが指摘したように、ヒープを圧縮する簡単な方法はありません。ただし、非常に一般的なケースである、時間の経過とともにテーブルが徐々に増加する場合、削除によって解放されたスペースが新しいデータで満たされるため、無駄はほとんどありません。

私が見たいくつかのヒープとクラスター化されたテーブルの議論は、インデックスのないヒープは常にテーブルスキャンを必要とするという点でクラスター化されたテーブルよりも劣るという奇妙なストローマンの議論をしています。これは確かに当てはまりますが、より意味のある比較は、「大規模な適切にインデックス化されたクラスター化テーブル」と「大規模な適切にインデックス化されたヒープ」です。テーブルが非常に小さい場合、または常にテーブルスキャンを実行する場合は、クラスター化してもしなくてもかまいません。

クラスター化されたテーブルの各インデックスはクラスター化インデックスを参照するため、実際にはすべてのインデックスをカバーしています。インデックス付き列とクラスタリング列を参照するクエリは、テーブル検索なしでインデックススキャンを実行できます。クラスタリングインデックスが合成キーである場合、これは一般に価値がありませんが、とにかく取得する必要があるビジネスキーである場合、それは素晴らしい機能です。

TL; DR

私はデータウェアハウジングの専門家であり、OLTPの専門家ではありません。ファクトテーブルでは、ほとんどの場合、範囲スキャン(通常は日付フィールド)が必要になる可能性が高いフィールドでクラスタリングインデックスを使用します。ディメンションテーブルの場合、PKでクラスター化するため、ファクトテーブルに対するマージ結合のために事前に並べ替えられます。

クラスタリングインデックスを使用する理由はいくつかありますが、これらの理由のいずれも当てはまらない場合、オーバーヘッドは価値がない可能性があります。クラスター化インデックスを普遍的に使用している人々の背後には、多くの「常にこの方法で行ってきた」および「ベストプラクティスである」と思われます。両方を試してみて、あなたのデータおよびあなたの負荷と最高の作品かを参照してください。


5

「インポート/エクスポート/ ETLプロセスで使用されるステージングテーブルに対してのみ有効な使用」と言うのは、控えめに言っても少し制限があると思います。特定のシステムの予想されるユースケースを採用し、ヒープまたはインデックス編成テーブルのメリットに基づいて選択する必要があります(Oracleの用語ですが、うまく説明しています)。

ウェアハウスは1日あたり15億行をロードし、読み取りだけでなく同時書き込みと処理を高度にサポートする必要があります。リレーショナルストアはOLAPデータベースをサポートしているため、読み取りは主にテーブルスキャンになる傾向があります。生成されるレポートとダウンストリームフィードも、一般に選択性が低いため、インデックスが有用です。システムはデータのスライディングウィンドウをサポートしているため、テーブルが読み込まれると再び書き込むことはほとんどなく、パーティション分割、スイッチ、マージに対してSch-Mロックを必要とするテーブルパーティショニングの実装が不十分であるため、読み取りなどにはSch-Sロックが使用されます、いくつかのパーティションテーブルもありますが、システムは多くのテーブルを使用する必要がありました。多くのテーブルを使用すると、データのセグメント化とクリーンアップサイクルが容易になり、競合も減少します。

そのため、ヒープにbcpを実行し、OLAPパーティションを処理し、テーブルスキャンクエリを実行してから3日後に削除できることに対して、任意の列にあるインデックス構成テーブル(クラスター化テーブル)のオーバーヘッドが増加します。それだけの価値はありません。この場合、データは大きなグリッドクラスターから返されるため、データの順序付けも行われないため、クラスター化インデックスを使用してテーブルに挿入すると、「ホットスポット」やページ分割などの他の問題が発生する可能性があります。

また、ページが散らばっているという議論は少し不誠実だと思います。クラスター化インデックスでは、ファイル全体にページを分散させることもできます。インデックスを再作成した後(1000ページ以上を想定)、これはヒープよりも優れている可能性がありますが、その後もインデックスを再作成する必要がありました。

スパース列と圧縮を使用してスペースを節約することもできます。場合によっては、クラスター化インデックスを使用したテーブルの選択が高速になることもありますが、それをロードして維持するために必要なリソースで比較検討する必要があります。

[編集]パーティション化されていないファクトテーブルのみがヒープであることを明確にする必要があります。パーティションテーブルとディメンションテーブルにはすべて、効率的なルックアップなどをサポートするクラスター化インデックスがあります。[Edit2] 25億から15億に修正しました。ツタンカーメン、これらの2つの数字は隣り合っています。電話で応答を入力するとどうなりますか?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.