在 FK 字段上使用 WHERE 的非常慢的 SELECT 语句

Extremely slow SELECT statement with WHERE on a FK field

我在下面有这个查询,它非常慢。 运行 return 9900 万条记录中的 table 3,008 条记录几乎需要 2 分钟。它获取 "Article" 数据的第一个查询非常快,不到 1 秒,并且总是 returns 1 条记录。这是问题所在的第二个查询。我真的不想加入这些查询。第一个是如此之快,而且(在我的真实查询中)我设置的不仅仅是 @ArticleID 以供进一步使用。

查询执行计划说它在 IX_Name 上的集群键查找中有 75% 用于它,这对我来说没有意义,因为我在这里甚至没有对名称字段做任何事情。此外,Id 和 ArticleID 都是 ArticleAuthor 的索引,所以我不确定我做错了什么。 IX_Name 作为聚集索引,我无能为力...我的老板创建了这个 table 并说要那样做。

DECLARE @DOI VARCHAR(72) = '10.1140/EPJC/S10052-012-1993-2'

DECLARE @ArticleID VARCHAR(12) 

SELECT 
    @ArticleID = A.Id
FROM
    Article A 
LEFT JOIN 
    JournalName JN WITH (NOLOCK) ON JN.Id = A.JournalId 
WHERE 
    A.DOI = @DOI

PRINT 'GOT ARTICLE DATA ' + format(getdate(), 'yyyy-MM-dd HH:mm:ss.fff')

SELECT 
    AA.Id 
FROM 
    [ArticleWarehouseTemp]..ArticleAuthor AA WITH (NOLOCK)
WHERE 
    AA.ArticleID = @ArticleID 

PRINT 'GOT ARTICLEAUTHOR DATA ' + format(getdate(), 'yyyy-MM-dd HH:mm:ss.fff')

请帮忙!这让我发疯。我也在这里附加了 table 结构和索引。

CREATE TABLE [dbo].[ArticleAuthor]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[ArticleId] [int] NOT NULL,
[FullName] [nvarchar](128) NULL,
[LastName] [nvarchar](64) NULL,
[FirstName] [nvarchar](64) NULL,
[FirstInitial] [nvarchar](1) NULL,
[OrcId] [varchar](36) NULL,
[IsSequenceFirst] [bit] NULL,
[SequenceIndex] [smallint] NULL,
[CreatedDate] [smalldatetime] NULL CONSTRAINT [DF_ArticleAuthor_CreatedDate]  DEFAULT (getdate()),
[UpdatedDate] [smalldatetime] NULL,
[Affiliations] [varbinary](max) NULL
) ON [ArticleAuthorFileGroup] TEXTIMAGE_ON [ArticleAuthorFileGroup]
GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[ArticleAuthor] WITH CHECK 
   ADD CONSTRAINT [FK_ArticleId] 
   FOREIGN KEY([ArticleId]) REFERENCES [dbo].[Article] ([Id])
GO

ALTER TABLE [dbo].[ArticleAuthor] CHECK CONSTRAINT [FK_ArticleId]
GO

CREATE NONCLUSTERED INDEX [IX_ID] 
ON [dbo].[ArticleAuthor] ([Id] ASC)

CREATE NONCLUSTERED INDEX [IX_ArticleID] 
ON [dbo].[ArticleAuthor] ([ArticleId] ASC)

CREATE CLUSTERED INDEX [IX_Name] 
ON [dbo].[ArticleAuthor] ([LastName] ASC, [FirstName] ASC, [FirstInitial] ASC)

您正在声明 DECLARE @ArticleID VARCHAR(12) 而它在您的 table [dbo] 中是 int。[ArticleAuthor][ArticleId] [int] NOT NULL,

尝试使它们具有相同的数据类型以确保更快的响应。

如果您必须保持当前聚集索引不变,您可以执行以下操作:

1.

确保您使用的类型正确:

DECLARE @ArticleID VARCHAR(12) 

应该是

DECLARE @ArticleID int;

匹配 ArticleAuthor table 中列 ArticleId 的类型。

2.

为了确保索引 IX_ArticleID 被有效使用,使其成为覆盖索引,INCLUDEId 到它:

CREATE NONCLUSTERED INDEX [IX_ArticleID] 
ON [dbo].[ArticleAuthor] ([ArticleId] ASC)
INCLUDE(Id);

3.

如果您的数据分布非常不均匀,即每 ArticleId 的行数因文章而异。比如说,如果一篇文章有​​ 2 行而另一篇文章有​​百万行,那么您最好将 OPTION(RECOMPILE) 添加到查询中并确保统计信息 and/or 索引保持最新。