2

次のテーブルがあるとします。

Table: RelationshipType
============================================================
|  ID (PK)  |  ParentID  |  ChildID  |  RelationshipType   |
============================================================

ほとんどの場合、ParentIDChildIDが個別に選択されています。

... WHERE ParentID = @SomeID

... WHERE ChildID  = @SomeID

また、両方が選択されている場合もあります。

... WHERE ParentID = @SomeID AND ChildID  = @SomeOtherID

私はこれらのクエリのパフォーマンスを向上させたいと考えていますが、特に最初の 2 つのパフォーマンスを向上させたいと考えています。ParentID+に非クラスター化インデックスをChildID一緒に作成するか、または に 1 つのインデックスParentIDと に別のインデックスを作成する必要がありChildIDますか?

編集: これらのクエリはすべて非常に選択的です (1 つまたは 2 つのレコードが返されます)。

4

4 に答える 4

3

代理キーを取り除くことはできますIDか?

はいの場合は、次の作成を検討してください。

  • 上のプライマリおよびクラスタリングキー{ParentID, ChildID}
  • のセカンダリ インデックス{ChildID, ParentID}ですが、インデックスにも含めます ( INCLUDEキーワードRelationshipTypeを使用します)。

このように、 3 つのケースすべてでカバリングインデックスがあるため、ダブル ルックアップの代価を支払う必要はありません (通常、クラスター化されたテーブルのセカンダリ インデックスに必要です)。

  • ... WHERE ParentID = @SomeIDインデックスの B ツリーでの単純なシークで満たすことができます: {ParentID, ChildID}ChildIDおよびRelationshipType1の値は、この B ツリーの見つかったリーフから直接取得できます。
  • ... WHERE ChildID = @SomeIDインデックスの B ツリーでの単純なシークで満たすことができます: {ChildID, ParentID}ParentIDおよびRelationshipType2の値は、この B ツリーの見つかったリーフから直接取得できます。
  • ... WHERE ParentID = @SomeID AND ChildID = @SomeOtherIDどちらでも満足できます。

1クラスタリング キーはテーブルの「メイン」B ツリーであり、一意の列だけでなく、すべての列が含まれます。

2に感謝しINCLUDE (RelationshipType)ます。


現在と同様のことを行うことIDは可能ですが、2 つではなく 3 つのインデックスが必要になり、カバーを達成するにはすべてが太くなります。確実に測定する必要がありますが、これは価値があるよりも面倒なことになると思います.

それ以外の場合は、クラスタリングをまったく使用しないでください。以下に通常のインデックスを作成するだけです。

  • {ID}- 通常の非クラスタ プライマリ インデックス (NONCLUSTERED キーワードを使用)。
  • {ParentID}- 通常のセカンダリ インデックス。
  • {ChildID}- 通常のセカンダリ インデックス。

通常のヒープ テーブルがあるため、アクセスごとにインデックス シーク + (通常は) テーブル ヒープ アクセスが必要になりますが、インデックスはスリムに保たれ、キャッシュの有効性が向上します。

... WHERE ParentID = @SomeID AND ChildID = @SomeOtherID2つのインデックスシーク(または、どちらか{ParentID}または{ChildID}インデックス+テーブルヒープアクセスのシーク)が必要になりますが、これはまだかなり高速であり、頻繁ではありません(あなたが述べたように)。


いずれかの方法を決定する前に、現実的な量のデータを測定してください。

于 2013-01-21T17:53:44.287 に答える
1

あなたがどちらParentIdChildIdで検索するか、非常に選択的であると言うように、私は2つの別々のインデックスを探します。

SQL Serverは、のいずれかのインデックスを使用してWHERE ParentID = @SomeID AND ChildID = @SomeOtherID、一致する1つまたは2つの行の残りの述語を評価できます。

例外は、テーブルが多かれ少なかれ読み取り専用であり、データベース全体がメモリに収まる場合、追加のインデックスを持つことのマイナス面はなく、欠落している列を取得するためのルックアップを回避することだと思います。

于 2013-01-21T12:22:48.287 に答える
1

ある意味で、これらの各選択の頻度とテーブルへの挿入/更新が発生する頻度を知らなければ、データベースに最高のパフォーマンスをもたらすものを言うことは不可能ですが、これが私の最善の推測です:

ParentIDのように聞こえますが、ChildIDが主キーである可能性があります。これは、定義上、クラスター化インデックスです。

ここでそれを行うための怠惰な方法は、ParentIDとChildIDにさらに2つの非クラスター化インデックスを作成することです。しかし...特にParentID列、または主キー/クラスターインデックスの最初に来る列-別の非クラスター化ParentIDインデックスを作成した場合に、選択したメリットが得られるかどうかはわかりません。非クラスター化インデックスは、そのインデックスで順序付けられたテーブルのコピーを格納しますが、この場合、主キーはテーブルの順序を決定し、最初に、ParentIDによって既に順序付けられています。

したがって、結論として、ParentIDとChildIDの主キーと、ChildIDの非クラスター化インデックスを作成します。これで、問題はないと思います。

于 2013-01-21T12:24:42.190 に答える
1

各列に単一の非クラスター化インデックスを作成しますが、他の列と RelationshipType 列も含めます (RelationshipType は取得するデータであると想定しています)。

CREATE NONCLUSTERED INDEX IX_RelationshipType_ParentID
ON
    RelationshipType(ParentID)
INCLUDE
    (ChildID, RelationshipType)
GO

CREATE NONCLUSTERED INDEX IX_RelationshipType_ChildID
ON
    RelationshipType(ChildID)
INCLUDE
    (ChildID, RelationshipType)
GO

これにより、エンジンはエントリを見つけた後、インデックス内のアイテムを見つけた後にテーブルに戻る必要なく、インデックスから目的のデータを取得できるようになります。

于 2013-01-21T12:36:45.370 に答える