SQL Server如何优化获取具有最大值的相关记录的查询
Posted
技术标签:
【中文标题】SQL Server如何优化获取具有最大值的相关记录的查询【英文标题】:SQL Server how to optimise this query which gets related records with a max value 【发布时间】:2018-02-26 16:15:21 【问题描述】:我有一个数据库视图,它需要从表中的两行获取值,在这里我们将其称为 Jobs。
除了主作业 (J1) 之外,查询还需要找到具有相同 CustomerID 的作业 (J2),但在所有此类作业中,J2 是具有最早截止日期的任务的作业。请注意,没有客户表,它只是匹配 ID。如果这没有意义,请参阅下面的查询!
SELECT J1.ID, J2.ID
FROM Jobs J1, Jobs J2
WHERE J2.ID = (SELECT Job_ID FROM Tasks T1
WHERE T1.Job_ID = J2.ID
AND T1.Deadline = (SELECT MIN(Deadline)
FROM Tasks T2, Jobs J3
WHERE T2.Job_ID = J3.ID
AND J3.CustomerID = J1.CustomerID))
上面的查询是正确的,但是很慢:如果你用 TOP 5 限制它是 38 秒。我不知道如何优化这个,有人可以帮忙吗?
编辑:
以下是执行计划。由于保密原因,我的表名已更改,因此我不得不在图像编辑器中对其进行更改。
主视图(这将是其中的一部分)使用 LEFT OUTER JOIN 代替。如果您使用这个修改后的查询,前 5 行的执行时间会下降到 9 秒,而整个数据库的执行时间会下降到 10 秒:
SELECT TOP 5 J1.ID, J2.ID
FROM Jobs J1 LEFT OUTER JOIN Jobs J2
ON J2.ID = (SELECT Job_ID FROM Tasks T1
WHERE T1.Job_ID = J2.ID
AND T1.Deadline = (SELECT MIN(Deadline)
FROM Tasks T2
LEFT OUTER JOIN Jobs J3
ON T2.Job_ID = J3.ID
AND CustomerID = CustomerID))
在 Job_ID 上的 Tasks 表上创建聚集索引可节省大约 10-20%。
【问题讨论】:
涉及优化的问题应包括解释计划。如果没有它,我们会猜测您的瓶颈在哪里以及可以做些什么来优化。它还有助于包含MCVE 和预期结果,以便人们可以在传递答案之前使用 SQL 以确保其正常运行。 sqlblog.org/2009/10/08/bad-habits-to-kick-using-old-style-joins 【参考方案1】:我的解决方案是创建一个视图:
ALTER VIEW EarliestJob AS
SELECT J1.ID AS JobID, J2.ID AS EarliestJobID, ROW_NUMBER() OVER(PARTITION BY J1.ID ORDER BY T.Deadline) AS RowNumber
FROM Jobs J1
LEFT OUTER JOIN Jobs J2 ON J1.CustomerID = J2.CustomerID
LEFT OUTER JOIN Tasks T ON J2.ID = T.Job_ID
查询就变成了:
SELECT JobID, EarliestJobID
FROM EarliestJob
WHERE RowNumber=1
1884 行的执行时间从 8 秒减少到 0.056 秒!
如果有人知道如何在不使用视图的情况下执行此操作,我会很感兴趣,我尝试将 ROW_NUMBER() 函数作为带有 =1 的 where 子句,但它不起作用 - 它只会返回所有行。
【讨论】:
以上是关于SQL Server如何优化获取具有最大值的相关记录的查询的主要内容,如果未能解决你的问题,请参考以下文章
Sql Server 优化 SQL 查询:如何写出高性能SQL语句