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 Server / T-SQL:查询优化帮助

Sql Server 优化 SQL 查询:如何写出高性能SQL语句

如何从SQL Server的字符串中获取最大的数字?

SQL Server调优系列玩转篇三(利用索引提示(Hint)引导语句最大优化运行)

如何在SQL Server中获取具有复合主键的表列表?