クラスター化インデックスは一意である必要がありますか?


83

クラスタ化インデックスが一意でない場合はどうなりますか?挿入された行が何らかの「オーバーフロー」ページに流れるため、パフォーマンスが低下する可能性がありますか?

それは「作られた」ユニークなものですか?もしそうなら、どのように?それをユニークにするための最良の方法は何ですか?

現在、クラスター化インデックスを使用してテーブルを論理部分に分割しているので質問していますが、パフォーマンスはまあまあで、最近、クラスター化インデックスを一意にするようアドバイス受けました。それについてセカンドオピニオンをお願いします。

ありがとう!

回答:


90

それらは一意である必要はありませんが、確かに推奨されます。
一意でない列にCIを作成したいというシナリオはまだ発生していません。

一意でない列にCI作成するとどうなりますか

クラスター化インデックスが一意のインデックスでない場合、SQL Serverは、一意化子と呼ばれる内部で生成された値を追加することにより、重複するキーを一意にします

これはパフォーマンスの低下につながりますか?

一意化子を追加すると、計算と保存にある程度のオーバーヘッドが確実に追加されます。
このオーバーヘッドが目立つかどうかは、いくつかの要因によって異なります。

  • テーブルに含まれるデータの量。
  • 挿入率はいくらですか。
  • 選択でCIが使用される頻度(カバーするインデックスが存在しない場合、ほとんどの場合)。


Remusがコメントで指摘しているように編集しますが、一意でないCIを作成することが合理的な選択となるユースケースが存在します。これらのシナリオの1つに遭遇しなかった私は、単に私自身の露出または能力の欠如を示しています(選択してください)。


30
+1は、あなたが言うことはすべて正しいが、追加したかっただけです。特定の(一意ではない)列の範囲スキャンが一般的なアクセスパターンである場合、一意でないCIは非常に一般的です。
Remus Rusanu 2010

@Remus Rusanu:シナリオステートメントに免責事項を追加すること考えていましたが、それは何の意味もありません。それが役立つかもしれないシナリオを指摘してくれてありがとう。
Lieven Keersmaekers 2010

4
@Remus:つまり、「DepartmentId BETWEEN 1 and100」のようなクエリを実行する「Departmentid」のような一意でない列があるニッチな状況を意味しますか?編集ああ私はあなたが何を意味するのかわかります、はい、ロギングテーブルの日付列も良い例です。
littlegreen 2010

ねえ、タイプGUIDの列である同じ「AggregateId」を持つ複数の行が存在するイベントストリームテーブルがあります。テーブルに対して実行されるクエリは、特定のAggregateIdのすべてのイベントを取得することだけです。これはクラスター化インデックスなのか、非クラスター化インデックスなのか疑問に思います。
Shayan C

@ ShayanC-取得のパフォーマンスが主な目標である場合、特定のIDのすべての行を取得するときに、IOを節約できる可能性が高いCIにします。ただし、すべてのパフォーマンスシナリオと同様に、確実な唯一の方法は測定することです。
LievenKeersmaekers18年

32

インデックス作成の女王、キンバリー・トリップがこのトピックについて何と言っているかを確認したいと思います。

いくつかの理由から、クラスタリングキーの推奨事項から始めます。まず、決定は簡単です。次に、この決定を早期に行うことで、特定の種類の断片化を予防的に防ぐことができます。特定の種類のベーステーブルの断片化を防ぐことができる場合は、テーブルをオフラインにする必要があるいくつかのメンテナンスアクティビティ(SQL Server 2000では一部、SQL Server 2005ではそれ以下)を最小限に抑えることができます。OK、後で再構築するものに行きます.....

クラスタリングキーで私が探す重要なことから始めましょう:

* Unique
* Narrow
* Static

なぜユニークなのですか? クラスタリングキー(存在する場合)は、すべての非クラスター化インデックスからのルックアップキーとして使用されるため、クラスタリングキーは一意である必要があります。たとえば、本の裏にあるインデックス(インデックスエントリが指すデータを見つける必要がある場合)を例にとると、そのエントリ(インデックスエントリ)は一意である必要があります。そうでない場合、どのインデックスエントリが探しているのでしょうか。 ?したがって、クラスター化インデックスを作成するときは、一意である必要があります。ただし、SQL Serverでは、クラスタリングキーを一意の列に作成する必要はありません。任意の列に作成できます。内部的には、クラスタリングキーが一意でない場合、SQLServerは4バイト整数をデータに追加することによってそれを「一意化」します。したがって、クラスター化インデックスが一意ではないものに作成された場合、インデックス作成時に追加のオーバーヘッドが発生するだけでなく、無駄なディスク領域が発生します。

出典: ますます増加するクラスタリングの重要な議論-再び!


質問ですが、女王はデータを一意化するためにnewsequentialidを推奨していますが、指定しない場合、SQLServerは独自の一意化子を生成します。それでも、独自のシーケンシャルIDを追加する理由はありますか?
littlegreen 2010

2
@littlegreen:GUIDの使用を主張する場合(クラスタリングインデックスでの使用には非常に悪い)、少なくともnewsequentialid()ほぼシーケンシャルなGUIDを取得するために使用すると彼女は言います。ただし、はい。独自のID追加すると(私は常にINT IDENTITYを好みます)、その値が手元にあり、それを使用できます(たとえば、FK関係を確立するため)。SQL Serverで追加された一意のファイアは表示されないため、使用できないオーバーヘッドにすぎません。
marc_s 2010

そうですか。それは、最初の2つだけではなく、(CompanyID、DepartmentID、id INT IDENTITY)クラスター化インデックスを支持する議論になります。ありがとう!
littlegreen 2010

1
@littlegreen:さらに良い- (ID INT IDENTITY)でのみクラスター化インデックスを作成し、必要に応じて他のフィールドを別の非クラスター化インデックスに配置します。クラスター化インデックスは可能な限り小さくする必要があります-結局のところ、クラスター化インデックス列は、そのテーブルのすべての非クラスター化インデックスのすべてのエントリにも追加されます-したがって、広いクラスター化でバイトを無駄にしないでくださいインデックス!
marc_s 2010

1
はい。ただし、すべての部門データがグループ化されるというメリットが失われ、部門全体を一度に挿入/削除/取得できるようになります。私のデータは散らばり、部門全体または会社全体での挿入/削除が遅くなります。私のクエリは一度に1つの会社でのみ実行され、データセット全体を更新する必要があることがよくあります。
littlegreen 2010

9

クラスター化インデックスは一意である必要がありますか?

そうではなく、そうでない方が良い場合もあります。

半ランダムで一意のEmployeeIdと各従業員のDepartmentIdを持つテーブルについて考えてみます。selectステートメントが

SELECT * FROM EmployeeTable WHERE DepartmentId=%DepartmentValue%

次にDepartmentId、が一意のインデックスではない場合でも(または特に理由で)、がクラスター化インデックスである場合、パフォーマンスに最適です(特定のDepartmentId内のすべてのレコードがクラスター化されるため、パフォーマンスに最適です)。


参考文献はありますか?

ありますクラスタ化インデックスの設計ガイドラインは、述べていた、例えば

いくつかの例外を除いて、すべてのテーブルには、以下を提供する1つまたは複数の列にクラスター化インデックスを定義する必要があります。

  • 頻繁に使用されるクエリに使用できます。
  • 高度な独自性を提供します。
  • 範囲クエリで使用できます。

たとえば、「高度な一意性」についての私の理解は、クエリのほとんどが特定の町内のレコードを選択する場合、クラストインデックスとして「国」を選択するのは良くないということです。


ええ、今までそう思っていたのですが、正反対のアドバイスもあるので、どちらが本当なのか気になります。参考文献はありますか?
littlegreen 2010

@littlegreenあなたの質問に答えようと、答えを編集しました。
ChrisW 2010

ありがとう。ええ大丈夫、私はあなたのポイントを見る。ただし、定期的に国全体を一度に挿入する場合、(国、町)のクラスター化インデックスは、データの並べ替えが必要になるため、面倒に思えます。一方、挿入前の並べ替えはそれほど問題にはなりません...
littlegreen 2010

3
確かにあなたの例では、{DepartmentID、EmployeeID}の一意のクラスター化インデックスが望ましいでしょうか?既存のフィールドがより少ないオーバーヘッド(おそらく4バイトのINT)で一意性を提供し、インデックス内だけでさらにいくつかのクエリを実行できるのに、なぜシステムが一意化子を作成するのですか?
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.