【发布时间】:2020-08-02 23:55:44
【问题描述】:
以下两个查询是用 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 行,表格 [Cants] 有 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 生成的。
如果您需要更多信息,我很乐意提供。
【问题讨论】:
-
你能在这里分享你的计划吗:brentozar.com/pastetheplan 如果你只提供计划的图片,很多细节都会丢失。
-
你能分享一下 Cols 和 Cants 表的索引吗?
-
好像执行计划的不同与表的行数有关。如果我们从 600 Cols 行移动到 1000000(难以置信),查询就会成功
-
那么你能上传粘贴计划实际显示问题的计划吗?扫描
标签: sql sql-server sql-execution-plan