複数のインデックスと複数列のインデックス


646

SQL Server 2005でテーブルにインデックスを追加したばかりで、考えていました。1つのインデックスを作成することと、インデックスを作成する列ごとに1つのインデックスを持つよりも複数の列を定義することの違いは何ですか。

一方を他方よりも使用する必要がある特定の理由はありますか?

例えば

Create NonClustered Index IX_IndexName On TableName
(Column1 Asc, Column2 Asc, Column3 Asc)

Create NonClustered Index IX_IndexName1 On TableName
(Column1 Asc)

Create NonClustered Index IX_IndexName2 On TableName
(Column2 Asc)

Create NonClustered Index IX_IndexName3 On TableName
(Column3 Asc)

回答:


319

Cade Rouxに同意します。

この記事はあなたを正しい軌道に乗せるはずです:

注意すべきことの1つは、クラスター化インデックスには、最初の列として一意のキー(私がお勧めするID列)が必要です。基本的には、インデックスの最後にデータを挿入するのに役立ち、多くのディスクIOとページ分割を引き起こしません。

次に、データに他のインデックスを作成していて、それらが巧妙に構築されている場合、それらは再利用されます。

たとえば、3つの列でテーブルを検索するとします。

州、郡、郵便番号。

  • 州のみで検索することもあります。
  • 州や郡で検索することもあります。
  • 州、郡、郵便番号で頻繁に検索します。

次に、州、郡、郵便番号のインデックス。これら3つの検索すべてで使用されます。

zipだけでかなり多く検索する場合、zipはそのインデックスの3番目の部分であり、クエリオプティマイザーはそのインデックスを役に立たないと見なすため、上記のインデックスは(とにかくSQL Serverによって)使用されません。

次に、このインスタンスで使用されるZipのみにインデックスを作成できます。

ちなみに、マルチカラムインデックスを使用すると、最初のインデックス列は常に検索に使用でき、「状態」のみで検索すると効率的ですが、「状態」のシングルカラムインデックスほど効率的ではありません。 」

あなたが探している答えは、それは頻繁に使用されるクエリのwhere句と、group byに依存するということです。

記事は大いに役立ちます。:-)


2
では、列ごとに個別のインデックスに加えて、州、郡、郵便番号のインデックスを定義するのが最善でしょうか?
Maxim

12
@jballここに何か不足していますか?この記事は主にSQL Serverのバージョン制限の違いについてのようです。記事は移動されましたか?
Ian R. O'Brien、

@Ianそれは、4年以上前に今から元のリンクを整理してから、間もなく3年で何かが失われたように見えます。ブログの投稿のタイトルはevilhomerによってリンクされたとおりですが、シリーズのフォローアップブログは最初の投稿から簡単に見つけられないようです。あなたは、シリーズの他のメンバーを上げることができるかどうかを確認するために、キンバリーのブログアーカイブをあちこち見回す必要があります。
jball 2013年

1
1)「基本的に[IDENTITY列を最初に持つクラスター化インデックス]は、インデックスの最後にデータを挿入するのに役立ちます」は正しいです。「多くのディスクIOとページ分割を引き起こさない」は、マルチユーザーシステムでは完全に偽です。真実は、マルチユーザーシステムで高い競合(低い同時実行性)を保証することです。2)クラスタ化インデックスは関係キーでなければなりません。ではありませんIDENTITY, GUID, etc。3)「その後、州、郡、郵便番号のインデックスが、これら3つの検索すべてで使用されます。」はfalseであり、「最初の列は使用可能」と矛盾します。インデックスの2番目とsubsの列は検索に使用できません。
PerformanceDBA

81

はい。インデックス作成に関するキンバリートリップの記事をチェックすることをお勧めします

インデックスが「カバー」している場合は、インデックス以外を使用する必要はありません。SQL Server 2005では、キーの一部ではない追加の列をインデックスに追加して、残りの行への移動を排除することもできます。

複数のインデックスがあり、それぞれが単一の列にある場合、使用されるインデックスは1つだけであることを意味します。実行プランを参照して、さまざまなインデックススキーマがもたらす影響を確認する必要があります。

また、チューニングウィザードを使用して、特定のクエリまたはワークロードを最適に実行するためのインデックスを決定することもできます。


7
キンバリー・トリップは彼女が何を話しているか知っています。私は彼女の話をしていました、そして彼女はこのことを完全に知っています。素晴らしいアドバイス。
evilhomer 2008年

@CadeRouxほとんどの場合、私のwhere句に「&」関係の2つの列がある場合、それらに複数列のインデックスを付けるか、両方に単一列のインデックスを付ける方がよいでしょう
これは、

2
@RachitGupta両方の列を持つ1つのインデックス
Cade Roux

40

複数列のインデックスは、すべての列を参照するクエリに使用できます。

SELECT *
FROM TableName
WHERE Column1=1 AND Column2=2 AND Column3=3

これは、複数列のインデックスを使用して直接検索できます。一方、単一列のインデックスを最大で1つ使用できます(Column1 = 1のすべてのレコードを検索し、それぞれの列2および列3を確認する必要があります)。


24
これは正しいです。ただし、これらの列をそれぞれ1つのインデックスとして使用しても、処理速度は大幅に向上します。通常、列の値の1つは結果セットを大幅に削減するため、インデックスなしで残りを検索する必要はなく、オプティマイザはこの値の選択に優れています。
TToni 2008年

16

見逃されているように見えるアイテムの1つは、星の変身です。 インデックス交差演算子は、ファクトテーブルでI / Oが実行される前に、各述語がヒットする行のセットを計算することで述語を解決します。スタースキーマでは、個々のディメンションキーにインデックスを付けます。クエリオプティマイザーは、インデックスの交差計算により、選択する行を解決できます。個々の列のインデックスは、これに対して最高の柔軟性を提供します。


質問に関連して、(通常の)インデックスがどのように使用されるかについてリンクされた適切な説明の+1。
RobM 2011

7

比較的静的な列のセットを頻繁に使用するクエリがある場合、それらすべてを含む単一のカバーするインデックスを作成すると、パフォーマンスが劇的に向上します。

インデックスに複数の列を配置すると、列がインデックスにない場合にのみ、オプティマイザはテーブルに直接アクセスする必要があります。私はこれらをデータウェアハウジングでよく使用します。欠点は、これを行うと、特にデータが非常に不安定な場合に、多くのオーバーヘッドが発生する可能性があることです。

単一の列にインデックスを作成することは、OLTPシステムで頻繁に見られるルックアップ操作に役立ちます。

なぜ列にインデックスを付けるのか、そして列がどのように使用されるのかを自問する必要があります。いくつかのクエリプランを実行し、いつアクセスされるかを確認します。インデックスのチューニングは科学と同じくらい本能です。

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