SQL SERVER为两个类似的查询生成不同且未经优化的执行计划

问题描述 投票:0回答:1

以下两个查询是使用SQL SERVER执行的>>

SELECT TOP(10) [c].[Name] AS [I0], [c].[Surname] AS [I1],(
    SELECT MAX([r].[Date])
    FROM [Presences].[Regs] AS [r]
    WHERE ([c].[Id] = [r].[ColId]) AND [r].[ColId] IS NOT NULL) AS [I7], [c].[Id] AS [I10]
FROM [Presences].[Cols] AS [c]
SELECT TOP(10) [c].[Code] AS [I0], [c].[Description] AS [I1], (
    SELECT MAX([r].[Date])
    FROM [Presences].[Regs] AS [r]
    WHERE ([c].[Id] = [r].[CantId]) AND [r].[CantId] IS NOT NULL) AS [I9], [c].[Id] AS [I10]
FROM [Presences].[Cants] AS [c]

第二个查询的评估时间少于1秒,但第一个查询花费的时间超过20秒。

实际上,为第一个生成的执行计划非常不同:

Bad execution plan of the first query

如果与第二个相比:

Good execution plan of the second query

我不清楚为什么不选择索引搜索。

这些是在表[Regs]上声明的索引:

CREATE NONCLUSTERED INDEX [IX_Regs_Date] ON [Presences].[Regs]
(
    [Date] ASC
)

CREATE NONCLUSTERED INDEX [IX_Regs_ColId] ON [Presences].[Regs]
(
    [ColId] ASC
)

CREATE NONCLUSTERED INDEX [IX_Regs_CantId] ON [Presences].[Regs]
(
    [CantId] ASC
)

[表[Cols]有大约600行,表[Cant] 21000。

有趣的事实是以下查询(使用FORCESEEK)生成了正确的执行计划:

SELECT TOP(10) [c].[Name] AS [I0], [c].[Surname] AS [I1],(
    SELECT MAX([r].[Date])
    FROM [Presences].[Regs] AS [r]
    WITH (FORCESEEK)  
    WHERE ([c].[Id] = [r].[ColId]) AND [r].[ColId] IS NOT NULL) AS [I8]
FROM [Presences].[Cols] AS [c]
ORDER BY [c].[Name], [c].[Surname]

但是由于查询是使用ORM生成的,所以我无法指定此提示。

如果您需要更多信息,我们将很乐意为您提供。

以下两个查询是通过SQL SERVER SELECT TOP(10)[c]。[Name] AS [I0],[c]。[Surname] AS [I1],(SELECT MAX([r]。[Date ])来自[状态]。[区域] AS [r]在([c]。[Id] = ...

sql sql-server sql-execution-plan
1个回答
0
投票

您的问题查询是

© www.soinside.com 2019 - 2024. All rights reserved.