3

どうしてこんなことができないの?この「共通」列のフィルターを高速にし、テーブルスキャンを必要とせずに返すことができるようにしたい。

CREATE NONCLUSTERED INDEX Ix_Foo
ON Foo (ForeignKeyID, ObjectID)
INCLUDE (ObjectID)

これを行うと、次のエラーが発生します。

インデックスで重複する列名を使用することはできません。列名'ObjectID'が複数回リストされています。

ObjectIDを返し、それでフィルタリングしたいこのようなクエリには、これが必要です。ここでのサブクエリは、私が意味するものの例です。

SELECT something FROM Bar
WHERE Bar.FooID IN
  (SELECT ObjectID FROM Foo WHERE ForeignKeyID=13 AND ObjectID IN (12, 13, 14, 15))

概念的に何が欠けていますか?

4

2 に答える 2

8

その理由はObjectIdすでにキー列としてインデックスに含まれており、非キー列としても含めようとしているため、不要です。

CREATE NONCLUSTERED INDEX Ix_Foo
ON Foo (ForeignKeyID, ObjectID)

これはあなたの目的には十分なはずです。

通常は、キー以外の列を含める必要があります(MSDNを引用)。

  • これらは、インデックスキー列として許可されていないデータ型にすることができます。

  • これらは、インデックスキー列の数またはインデックスキーサイズを計算するときにデータベースエンジンによって考慮されません。

于 2012-12-10T19:29:55.887 に答える
2

概念的には、SQL Serverのフィルター処理されていない、クラスター化されていないインデックスのリーフレベルには、基になるテーブルの行ごとに1行のデータがあります。リーフレベルの列は、以下とは異なる列です。

  • インデックスキーを構成する列。(インデックスをナビゲートできるように)
  • ベーステーブルの対応する行への概念的なポインタ。(したがって、ベーステーブルの対応する行に戻ることができます)
    • ヒープの場合、ポインターはRIDまたは行IDです。
    • クラスター化インデックスの場合、ポインターはクラスター化インデックスを構成するキー列です。
  • 含まれている列(適切な測定のために追加の列がスタックしている)

例えば:

CREATE TABLE t1 (id int not null, first_name varchar(20), last_name varchar(20))
CREATE CLUSTERED INDEX CIX_t1 on t1 (id)
CREATE INDEX IX_t1_a on t1 (first_name)
CREATE INDEX IX_t1_b on t1 (first_name) INCLUDE (id)
CREATE INDEX IX_t1_c on t1 (first_name) INCLUDE (id, last_name)
CREATE INDEX IX_t1_d on t1 (first_name, last_name)
CREATE INDEX IX_t1_e on t1 (first_name, id)

IX_t1_aのリーフレベルは、(first_name、id)で構成されます。

IX_t1_bのリーフレベルは、(first_name、id)で構成されます。

IX_t1_cのリーフレベルは、(first_name、id、last_name)で構成されます。

IX_t1_dのリーフレベルは、(first_name、id、last_name)で構成されます。

IX_t1_eのリーフレベルは(first_name、id)で構成されます

列が2回含まれることはありません。上記の例では、インデックスa、b、cは互いに重複しています。同様に、インデックスcとdも重複しています。(クラスター化インデックスと非クラスター化インデックスの一意性に応じて、非リーフレベルには微妙な違いがありますが、インデックスを使用できるクエリは同じです。)

于 2012-12-10T20:37:22.563 に答える