【问题标题】:In Microsoft SQL Server, will 2 non clustered indices improve performance when there is already a non clustered composite index?在 Microsoft SQL Server 中,当已经有一个非聚集复合索引时,2 个非聚集索引会提高性能吗?
【发布时间】:2022-01-09 00:20:26
【问题描述】:

我有一个名为 Files 的表,其中包含这些列

[Id] [int] IDENTITY(1,1) NOT NULL,
[RowVersion] [timestamp] NULL,
[CreatedAt] [datetime2](7) NOT NULL,
[UpdatedAt] [datetime2](7) NOT NULL,
[FileName] [nvarchar](450) NOT NULL,
[FileContent] [nvarchar](max) NULL,
[MessengerId] [int] NOT NULL,
[FileTypeId] [int] NOT NULL,
[Ref] [int] NOT NULL,

该表在主键 Id 上有一个聚集索引。

在 MessengerId 和 FileName 上还有一个非聚集复合索引

CREATE UNIQUE NONCLUSTERED INDEX [IX_Files_CourierId_FileName] ON [dbo].[Files]
(
    [MessengerId] ASC,
    [FileName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

这个查询很慢

SELECT COUNT(*) FROM Files WHERE MessengerId = 1 AND Filename = 'myfilename.xml'

我正在努力测试,因为超时发生在生产服务器上。在我的开发笔记本电脑上,我没有任何问题。

在 MessengerId 和 Filename 上添加 2 个新索引会提高性能吗?

这 2 个新索引看起来像这样

CREATE NONCLUSTERED INDEX [Index_on_FileName] ON [dbo].[Files]
(
    [FileName] 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, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO

CREATE NONCLUSTERED INDEX [Index_on_MessengerId] ON [dbo].[Files]
(
    [MessengerId] 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, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO

【问题讨论】:

  • 当前索引是覆盖索引,可以用来满足您的查询,而无需在表中查找行。两个提议的索引都没有覆盖,因此查询将不得不求助于表查找/扫描来查找剩余数据。您的问题可能是过时的统计数据或参数嗅探。还可以阅读Slow in the Application, Fast in SSMS?
  • 除了查询计划问题外,问题还可能是一般的服务器负载或持有行锁的应用程序(对于后者,您可以查看快照隔离等问题)。您唯一可以确定的不是问题是索引的有用性。如果您想知道(现有的或新的)索引是否有帮助,请始终查看之前和之后的查询计划;在这种情况下,应该告诉(即使在测试环境中)您的查询不会优先使用新索引而不是现有索引。

标签: sql-server indexing


【解决方案1】:

这个查询

SELECT COUNT(*) FROM Files WHERE MessengerId = 1 AND Filename = 'myfilename.xml'

需要在 MessengerIdFilename 上进行索引相等查找,并且没有其他列,因此您当前的索引就足够了。

您同样可以为相同的结果切换列顺序(如果没有匹配项,您可能会发现它快一点)

CREATE UNIQUE NONCLUSTERED INDEX [IX_Files_CourierId_FileName] ON [dbo].[Files]
(
    [FileName] ASC,
    [MessengerId] ASC
)

但是,您建议的另外两个新索引并未涵盖该查询,因此服务器很可能甚至不会费心使用它们,尤其是在您现有的查询仍然存在的情况下。当然,如果使用它们会更慢,因为它们需要对聚集索引进行键查找。


您的实际超时问题更可能与锁定有关,因为其他查询正在执行更新。我建议您使用查询来查找任何可能的阻止程序,例如this one

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-20
    • 1970-01-01
    • 2023-03-23
    • 2011-03-24
    • 2014-04-27
    • 2012-10-01
    • 2018-05-08
    相关资源
    最近更新 更多