【问题标题】:Overlapping of cover and single indexes in SQL ServerSQL Server 中覆盖索引和单个索引的重叠
【发布时间】:2010-11-11 12:50:39
【问题描述】:

我有一个关于在 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”?

【问题讨论】:

    标签: sql-server indexing covering-index


    【解决方案1】:

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

    如果您希望在不涉及Text 的查询上获得更高的SELECT 性能,您可能仍希望仅在ProfileID 上创建附加索引。

    但是,这有两个缺点:

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

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

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

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

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

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

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

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

    我按顺序(ProfileID,文本)创建了索引。如果为了论证的缘故,有 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).
    

    【讨论】:

    • @Quassnoi 听起来您是在说封面索引将部分帮助查询 ProfileID,但不如此列上的独立索引。跨度>
    • @IanC:复合索引的大小会更大,并且可能需要额外的时间来遍历它。由于较少的节点适合一页,因此索引深度可能会更大。可能需要5 页面查找才能找到具有复合索引的节点,而只有23 可以满足简单的索引。
    • 还要注意,你创建的并不是严格意义上的覆盖索引。在覆盖索引中,被覆盖的列不被排序或在查找中使用。
    • @Quassnoi 所以复合索引(覆盖索引)不是列的散列,而是实际上是数据,从而可以有效地搜索第一列或所有列。对吗?
    • @IanC: msdn.microsoft.com/en-us/library/ms188783.aspx 并查看G 部分。至于我,这很清楚。
    猜你喜欢
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 2014-08-16
    • 2011-05-09
    • 1970-01-01
    相关资源
    最近更新 更多