我在 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
我会对您的
Parts.ManufacturingData
表中的总行数以及您的查询当前的总运行时间感兴趣。执行计划说它返回的行数(大约 3200 万)实际上对您的查询有意义吗?也许您会发现过滤索引可以为您节省一点时间,因为它只会预先实现您想要的数据。具有此定义的索引怎么样,有什么区别吗?
请注意,一旦创建了上述过滤索引,您不需要对查询执行任何不同的操作即可使用它。但是您应该检查执行计划以确保优化器在查询运行时选择这个新索引而不是表上的任何其他索引。
如果这没有任何区别,您可以尝试的另一件事是将
FORCESCAN
提示添加到您的查询中,如下所示:这将告诉优化器使用扫描操作而不是搜索您的数据。如果表中的大部分数据符合您的
WHERE
子句标准,这通常会更有效。即,在该点扫描整个表并过滤掉不需要的行通常比查找这么多行要快。但是很难说这是否会在不了解您的数据或对其进行测试的情况下对您的情况有所帮助。请注意,应谨慎使用查询提示,并且仅在无法使用替代优化方法的情况下使用。某些查询提示限制了优化器可以选择的可用执行计划的数量,因此当使用这些提示的某些查询尝试执行时,可能会引发错误。
在这种情况下,我认为使用
FORCESCAN
提示可能没问题,因为您的查询很简单,而且我认为它不会像其他提示那样限制查询计划的数量。Mybe,您可以尝试在同一文件上使用非聚集列存储索引。这可能会导致批处理模式和压缩,因此您可以在阅读时节省一些东西。
微软文档
例子:
您的索引搜索返回 3200 万行。你有一个很好的计划,只是需要阅读大量数据。
您可以考虑在尝试插入目标表之前显式创建目标表。
除了其他正确答案之外,您还可以尝试另一种方法来提高性能,这可能是创建索引视图,如下所示:
创建上述视图后,创建索引如下:
创建上述视图和索引后,您可以将查询重写为:
我将查询更改为
insert into
而不是select * into
代码的可重用性。在 的情况下select into
,您总是需要删除基础表。请让我们知道这是否有帮助。