我们有一个生产存储过程,除了一个客户端的环境外,在2-3秒内执行。
他们的环境看起来很健康,有24个内核,64 GB RAM,而且容量不足。 SQL Server是2008 r2 SP2。
我已经在测试环境中恢复了数据库,并且sproc在2秒内返回,但在客户端环境中需要20-50分钟。
今天我在同一台服务器上设置了一个新的SQL Server实例,执行存储过程也需要20-50分钟。
我们的DBA找到了问题陈述并设计了一种解决方法。
原始:
--This returns in 30 minutes.
SELECT DISTINCT
P.ProjectID, P.ProjectName
FROM DocumentRoute DR
LEFT JOIN Routes R
ON R.RouteID = DR.RouteID
INNER JOIN Documents D
ON D.DocumentID = DR.DocumentID
AND D.Status = 1
INNER JOIN Files F
ON F.FileID = D.FileID
AND F.Status = 1
INNER JOIN Projects P
ON P.ProjectID = F.ProjectID
AND P.Status = 1
LEFT OUTER JOIN Users U
ON U.UserID = DR.UserID
WHERE DR.Status = 1
原始执行计划:http://screencast.com/t/xGcRIE9o
解决方法:
--This returns in 2 seconds.
SELECT DISTINCT
P.ProjectID, P.ProjectName
FROM DocumentRoute DR
LEFT JOIN Routes R
ON R.RouteID = DR.RouteID
AND DR.Status = 1
INNER JOIN Documents D
ON D.DocumentID = DR.DocumentID
AND D.Status = 1
INNER JOIN Files F
ON F.FileID = D.FileID
AND F.Status = 1
INNER JOIN Projects P
ON P.ProjectID = F.ProjectID
AND P.Status = 1
LEFT OUTER JOIN Users U
ON U.UserID = DR.UserID
此处修订执行计划:http://screencast.com/t/Fqg90w6NDyZd
客户环境中的哪些内容可能会导致执行时间的巨大差异?
其他信息:当我从客户端获得执行计划时,问题陈述本身在17秒内完成,但整个sproc已经运行了15+分钟,可能需要另外15分钟完成。
答案 0 :(得分:1)
第一个问题是这两个查询的含义不同,可能会返回不同的结果。第一个查询只会生成DocumentRoute
行Status = 1
。第二个查询将生成所有 DocumentRoute
行,并且Status
为null或不等于1时,将不会执行到Routes
的连接。 / p>
第二个问题是,如果您只是使用DISTINCT
从Projects表中选择列,则LEFT JOIN
无法以任何方式更改查询 - 因此您也可以删除它们。
最后,在没有让我们对两个查询的执行计划有所了解的情况下,可能还有一些关于所涉及表的结构的更多细节,没有人能够明确地给出你正在发生的事情的答案。此外, 环境中的执行计划(需要2秒)并不会有所帮助。我们必须知道运行缓慢的环境中的执行计划。
要获得执行计划,首先运行SET STATISTICS XML ON;
,运行所需的查询,并查看在查询结果集之后给出的结果集中显示的执行计划。
关于可能导致问题的一些想法:
答案 1 :(得分:0)
根据@ErikE的建议,我仔细检查了客户端对存储过程中多个语句的执行计划,并注意到了几个并行操作符。
因此,知道他们在服务器上有24个处理器而在我的服务器上有1个处理器,灯泡点亮了,我决定尝试MAXDOP为1,并且执行时间从45分钟变为2秒。
sp_configure 'show advanced options', 1;
RECONFIGURE WITH OVERRIDE;
GO
sp_configure 'max degree of parallelism', 1;
GO
RECONFIGURE WITH OVERRIDE