3

我有一个关于在 SQL Server(或任何 RDBMS)中建立索引的最佳实践的问题。取下表:

ProfileID int
Text      nvarchar(50)

ProfileID连接到一个Profile表。对于每个配置文件,每个配置文件都Text必须是唯一的。因此,我在两列上都放了一个主封面键。美好的。

但是,我也希望能够通过ProfileID. 所以我也放了一个索引ProfileID

这意味着我有一个重叠的索引。我不知道这是否完全浪费,因为已经有一个封面索引,或者它是否正确,因为封面索引将是两列的哈希(或者我误解了封面索引)?

编辑:

我按顺序创建了索引(ProfileID, Text)。如果为了论证的缘故,有 3 列 A、B 和 C,它们在所有 3 中都有一个覆盖索引。只有当我们针对“A”或“A、B 和 C”进行查询时它才会受益,但不是“B”,还是“C”,还是“B 和 C”?

4

1 回答 1

5

上的索引(ProfileID, Text)(按此顺序)也是上的索引ProfileID

ProfileID如果您希望在SELECT不涉及Text.

但是,这有两个缺点:

  1. 维护两个索引需要更多资源,并且DML查询 ( INSERT, UPDATE, DELETE) 的性能可能会受到影响

  2. 如果混合使用这两种类型的查询,则两种索引都会占用缓存,并且缓存未命中率可能比单个索引多。

    如果您的表足够小以与两个索引一起放入缓存中,这不是问题。

封面索引将是两列的哈希(或者我误解了封面索引)?

一个真正的覆盖索引将通过这种方式创建:

CREATE INDEX ix_mytable_profile__text ON mytable (ProfileID) INCLUDE (Text)

这样,Text只会存储在索引的叶级节点中。

但是,由于您需要UNIQUE索引,因此两列都需要成为键的一部分。节点在ProfileIDthen上按字典顺序排序Text

我按顺序(ProfileID、Text)创建了索引。如果为了论证的缘故,有 3 个列 A、B 和 C,它们的覆盖索引覆盖所有 3 个列。只有当我们针对“A”或“A、B 和 C”进行查询时,它才会受益,但不是“B”,还是“C”,还是“B 和 C”?

CREATE INDEX ix_mytable_a_b_c ON mytable (a, b, c)

SELECT  a, b, с
FROM    mytable
WHERE   a = 1 

-- Index lookup, no table lookup. a is leading

SELECT  a, b, с
FROM    mytable
WHERE   a = 1
        AND b = 1

-- Index lookup, no table lookup. (a, b) are leading.

SELECT  a, b, с
FROM    mytable
WHERE   b = 1

-- Index full scan (`b` is not leading), no table lookup

SELECT  a, b, с
FROM    mytable
WHERE   c = 1

-- Index full scan (`c` is not leading), no table lookup

SELECT  a, b, с, d
FROM    mytable
WHERE   a = 1

-- Index lookup, table tookup (d is not a part of the index).

SELECT  a, b, с, d
FROM    mytable
WHERE   b = 1

-- Table full scan (there is no point in using index at all, neither for lookup nor for covering).
于 2010-11-11T12:51:59.803 回答