3

Why can't I do something like the following? I want filters on this "common" column to be both fast and to also be able to return it without requiring a table scan.

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

When I do this, I get the error:

Cannot use duplicate column names in index. Column name 'ObjectID' listed more than once.

I'd like this for queries such as this where I both want to return ObjectID as well as filter by it. The subquery here is an example of what I mean:

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

What am I conceptually missing?

4

2 回答 2

8

原因ObjectId已经作为键列包含在索引中,而您也试图将其作为非键列包含,这是不必要的。

CREATE NONCLUSTERED INDEX Ix_Foo
ON Foo (ForeignKeyID, ObjectID)

这应该足以满足您的目的。

您通常需要包含非关键列,以便(引用MSDN):

  • 它们可以是不允许作为索引键列的数据类型。

  • 在计算索引键列数或索引键大小时,数据库引擎不会考虑它们。

于 2012-12-10T19:29:55.887 回答
2

Conceptually the leaf level in a non-filtered, non-clustered index in SQL Server has 1 row of data per row in the underlying table. The columns in the leaf level are the distinct columns from the following:

  • Columns that make up the index key. (So we can navigate the index)
  • A conceptual pointer to the corresponding row in the base table. (So we can get back to the corresponding row in the base table)
    • For a heap, the pointer is the RID, or row identifier
    • For a Clustered Index, the pointer is the key columns that make up the clustered index
  • Any included Columns (Extra columns stuck in for good measure)

For example:

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)

The leaf level of IX_t1_a consists of (first_name, id)

The leaf level of IX_t1_b consists of (first_name, id)

The leaf level of IX_t1_c consists of (first_name, id, last_name)

The leaf level of IX_t1_d consists of (first_name, id, last_name)

The leaf level of IX_t1_e consists of (first_name, id)

Columns are never included twice. In the example above, indexes a,b,c are duplicates of each other. Likewise, indexes c and d are duplicates as well. (There are subtle differences in the non-leaf levels depending on the uniqueness of clustered and non-clustered indexes, but for which queries the index can be used for, they are identical.)

于 2012-12-10T20:37:22.563 回答