小编Fle*_*tch的帖子

缺少非聚集索引已经是聚集索引的一部分

我正在调试运行缓慢的查询,并且在执行计划中建议使用非聚集索引,影响为 51.6648。但是,非聚集索引仅包括主键 (PK) 复合聚集索引中已经存在的列。

这可能是因为索引中列的顺序吗?即,如果聚集索引中的列不是按选择性从高到低的顺序排列,那么非聚集索引是否有可能提高性能?

此外,非聚集索引仅包含三个 PK 列中的两个,第三个添加为包含列。include使用非聚集索引可能更优化的另一个原因是什么?

下面是我正在使用的表结构的示例:

表-

Retailers (
    RetailerID int PK, 
    name ...)

Retailer_Relation_Types (
    RelationType smallint PK, 
    Description nvarchar(50) ...)

Retailer_Relations (
    RetailerID int PK FK, 
    RelatedRetailerID int PK FK, 
    RelationType smallint PK FK, 
    CreatedOn datetime ...)
Run Code Online (Sandbox Code Playgroud)

该表Retailer_Relations具有以下复合PK指数和建议指数-

CONSTRAINT PK_Retailer_Relations 
PRIMARY KEY CLUSTERED (
    RetailerID ASC, 
    RelatedRetailerID ASC, 
    RelationType ASC
    ) ON [PRIMARY]

CREATE NONCLUSTERED INDEX <NameOfIndex> 
ON Retailer_Relations (
    RetailerID, 
    RelationType
    ) 
INCLUDE (
    RelatedRetailerID
    )
Run Code Online (Sandbox Code Playgroud)

index sql-server execution-plan sql-server-2016

9
推荐指数
1
解决办法
895
查看次数

Covering Index Changes Execution Plan 但未使用

我有以下偶尔运行缓慢的查询:

SELECT C.CustomerID 
FROM dbo.Customers C WITH (NOLOCK)
WHERE C.Forename = @Forename
    AND C.Surname = @Surname
OPTION (RECOMPILE)
Run Code Online (Sandbox Code Playgroud)

CustomerID 是Customers 表上的主键。客户表还有以下两个非聚集索引:

CREATE NONCLUSTERED INDEX idx_Forename ON Customers (Forename ASC)
CREATE NONCLUSTERED INDEX idx_Surname ON Customers (Surname ASC)
Run Code Online (Sandbox Code Playgroud)

当我使用输入的姓氏和名字运行查询时,查询优化器使用索引“idx_Surname”,如以下执行计划所示:

不覆盖索引的执行计划

对于此特定搜索,此查询需要两分钟多的时间才能完成,并且未找到任何结果。对于输入的值,@Forename 在 Customers 表中没有匹配项,而 @Surname 匹配 31,162 条记录。当我只按 @surname 搜索时,31,162 条记录会在不到一秒钟的时间内返回,并采用以下计划:

执行计划仅姓氏搜索

为了优化包含 Forename 和 Surname 的搜索的查询,我添加了以下覆盖索引:

CREATE NONCLUSTERED INDEX idx_Surname_Covering ON dbo.Customers (Surname) INCLUDE (Forename)
Run Code Online (Sandbox Code Playgroud)

带有 Forename 和 Surname 的查询将在不到一秒的时间内返回。但是,实际执行计划中并没有使用覆盖索引:

带覆盖索引的执行计划

所以,

  1. 是否需要覆盖索引或有更好的方法来提高性能和
  2. 为什么额外的覆盖索引会导致实际执行计划中的索引从idx_Forename 变为idx_Surname?

ps 上面的查询是一个孤立的例子,在使用时,可以搜索姓氏或名字,或者两者都可以搜索,并且客户表还包括其他具有自己索引的可搜索列。这个细节被认为与问题无关,所以我没有包括它。

performance index sql-server execution-plan sql-server-2016 query-performance

4
推荐指数
1
解决办法
536
查看次数