web-dev-qa-db-ja.com

非一意のクラスタ化インデックスと一意のクラスタ化インデックスの一意化

たとえば、次のように構造化されたテーブルがあるとします。

ID1 int
ID2 int
ID3 int
DTM datetime

ID1、ID2、およびID3を含めた場合にのみ、テーブルに一意のクラスター化インデックスを作成できます(これらの2つを組み合わせるか、個別に行を重複させることになります)。

ID1、ID2、ID3でクラスター化インデックスを作成すると、パフォーマンスが向上しますか?または、ID1のみにクラスター化インデックスを作成し、SQL Serverにインデックスに一意化子を追加して各行を一意にしますか?

一意化子のサイズは4バイト(intと同じ)であることを知っているので、後者のインデックスを作成すると、技術的には1行あたり4バイトを節約できますが、これがクエリにどのように影響するかはわかりません。

4
John Odom

クラスター化インデックスのパフォーマンスに関する最も重要な考慮事項の1つは、それが常に増加(または減少)することであり、変更されるものではないことです(ごくまれに例外がある場合を除く)。クラスタ化インデックスは、テーブルの物理的な順序を表します。常にインデックスの中央に挿入している場合、またはクラスター化インデックスの値を変更している場合は、SQLがデータの一部をあるページから別のページに移動してスペースを空ける必要がある不良ページ分割が発生します。新しいデータ用。これらの移動には時間がかかり、断片化が発生してパフォーマンスが低下します。

クラスタインデックスのサイズは重要ですが、最大の懸念事項ではありません。 日付列(一意性のあるもの)とint列 を使用していくつかの実験を行ったところ、クエリが日付ベースの場合でも、パフォーマンスが大幅に向上することがわかりました。

あなたへの私の提案は、ID1、ID2、ID3が常に増加している(そしてほとんど変化しない)場合、それをクラスター化インデックスとして使用することです。そうでない場合でも、一意性を適用するには、それらを非クラスター化主キーまたは非クラスター化一意キーのいずれかにします。それらが増加していない場合は、日付列を検討するか、テーブルの代理キーを作成できます。 intデータ型を使用して、それをID列にします。

サロゲートキーを作成する場合は、ID1に非クラスター化インデックスを作成して、一意のインデックスをまだ作成していないと想定して、クエリのパフォーマンスを向上させることができます。 ID2やDTMなど、頻繁に戻る必要がある場合は、これらをインデックスに含めると、パフォーマンスがさらに向上します。

5
Kenneth Fisher

提案されたインデックスは、データ制約を強制するためのものですか、それともパフォーマンスを向上させるものですか?インデックスでレコードの重複を防止する場合は、3つのフィールドすべてを含める必要があります。

ただし、パフォーマンスを向上させようとしていて、クエリが通常ID1、別のオプションがあります。IDだけで一意でないインデックスを作成します。これは、いずれかの一意のインデックスよりも狭く、非一意のインデックスのパフォーマンスが著しく低下してはなりません。

サンプルクエリを共有する場合は、より具体的なアドバイスを提供できます。

2