我正在调试运行缓慢的查询,并且在执行计划中建议使用非聚集索引,影响为 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) 我有以下偶尔运行缓慢的查询:
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 的查询将在不到一秒的时间内返回。但是,实际执行计划中并没有使用覆盖索引:
所以,
ps 上面的查询是一个孤立的例子,在使用时,可以搜索姓氏或名字,或者两者都可以搜索,并且客户表还包括其他具有自己索引的可搜索列。这个细节被认为与问题无关,所以我没有包括它。
performance index sql-server execution-plan sql-server-2016 query-performance