【问题标题】:When to use a covering index, a composite index, and unique columnar indexes何时使用覆盖索引、复合索引和唯一列索引
【发布时间】:2010-11-11 15:44:21
【问题描述】:

假设我在 SQL Server 2008 中有下表:

ProfileID   int          //identity; index: unique, primary key, clustered
ClientID    int
RegionID    int
ProfileName nvarchar(50)

第 2 列和第 3 列通过外部关系链接到各自的表。

假设我最常见的查询是这样的:

SELECT ProfileID, ProfileName
FROM   Profiles
WHERE  ClientID = ? AND RegionID = ?
ORDER  BY ProfileName

哪种索引系统最适合?

如果我在 (ProfileID, ProfileName) 上放置一个覆盖索引,那么这会杀死默认的聚集索引,因为覆盖索引必须是非聚集索引,但至少满足查询的返回部分。

如果我保持原样保留主键,并独立索引 ClientID 和 RegionID,这给了我 3 个必须由 RDBMS 维护的索引,加上表扫描仍然需要返回 ProfileName,因为它不是覆盖。这似乎很重。

一个简单的案例研究,说明索引规划的复杂程度。

【问题讨论】:

    标签: sql-server database-design indexing rdbms


    【解决方案1】:

    对于这个查询:

    SELECT  ProfileID, ProfileName
    FROM    Profiles
    WHERE   ClientID = ? AND RegionID = ?
    ORDER BY
            ProfileName
    

    你应该创建这个索引:

    CREATE INDEX ix_profiles_region_client_name ON (RegionID, ClientID, ProfileName)
    

    (RegionID, ClientID) 的单个值内,记录按ProfileName 排序,因此记录将进行排序,无需额外排序。

    由于ProfileIDPRIMARY KEY CLUSTERED,它被隐式包含在每个索引记录中,因此不需要在索引定义中显式指定。

    如果它不是聚集键,则需要将其添加到索引中才能覆盖此查询:

    CREATE INDEX ix_profiles_region_client_name__id ON (RegionID, ClientID, ProfileName) INCLUDE (ProfileID)
    

    【讨论】:

    • @Quassnoi 我的朋友,你回来了。我假设您的意思是“......并留下主索引”?不只是这一个索引?
    • Quassnoi 我有两个问题:1)我认为 (ClientID, RegionID...) 会更好,因为 ClientID 是最独特的列(好吧,我没有在我的问题中提到这一点, 的确)。我认为顺序是最独特到最不独特的。第二个问题是为什么 ProfileName 在索引中,但不是作为包含列,当我们没有专门查询它时?
    • @Ianc:对于这个查询,它并不重要,因为搜索总是在整个元组(ClientID, RegionID) 上执行。但是,如果您需要单独搜索ClientID(或与RegionID 以外的列组合),则可以交换顺序。 ProfileName 在索引中,因为它在 ORDER BY 子句中使用。包含的列不按索引排序,因此如果您将 ProfileName 包含为非键列,则查询需要排序。
    • @Quassnoi 谢谢。最后一个问题,如果你不介意的话。如果我需要经常针对 ClientID 或 RegionID 进行搜索,您提供的索引是否仍然是最佳的?
    • @IanC:最好使用两个单独的索引:(ClientID, RegionID)RegionID
    猜你喜欢
    • 1970-01-01
    • 2012-03-24
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    相关资源
    最近更新 更多