mslid 上的非聚集索引查找速度很慢

ahm*_*ary 2 sql-server constraint stored-procedures execution-plan sql-server-2016

我在 SQL Server 中遇到一个问题,其中非聚集索引查找的性能很差。

下面是实际的执行计划 https://www.brentozar.com/pastetheplan/?id=Sk3-4JGAK

我怎样才能提高绩效?

下面是表定义

 CREATE TABLE [Parts].[ManufacturingData](
     [LeadFinishId] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
     [PartID] [int] NOT NULL,
     [LeadFinishMaterial] [varchar](50) NULL,
     [CreatedDate] [datetime] NULL,
     [CreatedBy] [int] NULL,
     [ModifiedDate] [datetime] NULL,
     [Modifiedby] [int] NULL,
     [DeletedDate] [datetime] NULL,
     [DeletedBy] [int] NULL,
     [Revision_Id] [int] NULL,
     [BaseMaterialID] [int] NULL,
     [MSLID] [int] NULL,
     [MSLSource_Revision_id] [int] NULL,
     [MaximumReflowTemperatureID] [int] NULL,
     [ReflowTemperatureSource_Revision_Id] [int] NULL,
     [MaximumWaveTemperatureID] [int] NULL,
     [WaveTemperatureSource_Revision_ID] [int] NULL,
     [ReflowSolderTimeID] [int] NULL,
     [WaveSolderTimeID] [int] NULL,
     [NumberOfReflowCycleID] [int] NULL,
     [LeadFinishPlatingID] [int] NULL,
     [Comment] [varchar](100) NULL,
     [LeadfinishSourceTypeID] [int] NULL,
     [MSlSourceTypeID] [int] NULL,
     [ReflowTemperatureSourceTypeID] [int] NULL,
     [BasedOnID] [int] NULL,
     [LeadFreeProcessCapabilityID] [int] NULL,
     [BaseMaterialRevisionID] [int] NULL,
     [BaseMaterialSourceTypeID] [int] NULL,
     [UnderplatingRevisionID] [int] NULL,
     [UnderplatingSourceTypeID] [int] NULL,
     [ShelfLifeCondition] [int] NULL,
  CONSTRAINT [PK_PartID] PRIMARY KEY CLUSTERED 
 (
     [PartID] ASC
 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Customer]
 ) ON [Customer]
    
 GO
    
 SET ANSI_PADDING ON
 GO

index seek used as below

 CREATE NONCLUSTERED INDEX [IDX_MSLID] ON [Parts].[ManufacturingData]
 (
     [MSLID] ASC
 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Customer]
 GO

USE [Z2DataCore]
GO


 ALTER TABLE [Parts].[ManufacturingData] ADD  CONSTRAINT [PK_PartID] PRIMARY KEY CLUSTERED 
 (
     [PartID] ASC
 )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Customer]
 GO
Run Code Online (Sandbox Code Playgroud)

J.D*_*.D. 5

我对表中的总行数Parts.ManufacturingData以及查询当前的总运行时间感兴趣。执行计划表示返回的行数(大约 3200 万)对于您的查询实际上有意义吗?

也许您会发现过滤索引可以为您节省一点时间,因为它只会预先具体化您想要的数据。具有这个定义的索引怎么样,有什么区别吗?

CREATE NONCLUSTERED INDEX IX_ManufacfuringData_MSLID_Filtered ON Parts.ManufacturingData (MSLID) WHERE MSLID IS NOT NULL;
Run Code Online (Sandbox Code Playgroud)

请注意,一旦创建了上述过滤索引,您不需要对查询执行任何不同的操作即可使用它。但是您应该检查执行计划,以确保优化器在查询运行时选择这个新索引而不是表上的任何其他索引。

如果这没有任何区别,您可以尝试的另一件事是将提示添加FORCESCAN到您的查询中,如下所示:

select  partid,mslid 
into ExtractReports.dbo.manufactureparts
from parts.manufacturingdata m with(nolock, FORCESCAN)
where mslid is  not null
Run Code Online (Sandbox Code Playgroud)

这将告诉优化器使用扫描操作而不是针对您的数据进行查找。如果表中的大约大部分数据满足子句的条件,这通常会提高性能WHERE。即,此时扫描整个表并过滤掉不需要的行通常比查找这么多行更快。但在不了解您的数据或对其进行测试的情况下,很难说这是否会对您的情况有所帮助。

请注意,应谨慎使用查询提示,并且仅在无法使用其他优化方法的情况下使用。某些查询提示限制优化器可以选择的可用执行计划的数量,因此当使用这些提示的某些查询尝试执行时可能会导致抛出错误。

在这种情况下,我认为使用FORCESCAN提示可能没问题,因为您的查询很简单,而且我不认为它像其他提示那样限制查询计划的数量。

  • @JD是的,您正在寻找的术语是“范围扫描”。另请参阅 [来自 Paul White] 的一篇优秀文章(https://www.sql.kiwi/2011/02/so-is-it-a-seek-or-a-scan.html) (2认同)