与SQL管理管理员相比,从ASP.NET调用存储过程的速度较慢



我们正试图诊断复杂存储过程中的速度缓慢(它有几个巨大的查询)。

当我们从ASP.NET调用SP时,需要5秒钟。

当我们从SQL Management Studio(仅使用EXEC)调用它时,它需要0.05秒。

我们已经在许多不同的方式和环境中一致地测试了这种行为。

这是用C#.NET创建的。数据库是MS SQL Server 2012。

问题出在web应用程序上,但我们编写了一个小型控制台应用程序作为测试工具,其行为是相同的。

1) 我们在C#控制台应用程序中计算经过的时间,如下所示:

stopwatch.Start();
rdr = cmd.ExecuteReader();
stopwatch.Stop();

2) 我们通过在查询前后调用GETDATE()来计算SQL过程中的运行时间,然后将这些时间存储在一个小表中。我们可以在SQL Mgmt Studio中查询该表,以查看SP内部的查询花费了多长时间。

通过这种方式,我们可以看到在SQL中花费了多少时间,而在整个SQL中花费的时间占99%。

但是,如果它在SQL Mgmt Studio中不是很慢,那么很难进行调试和改进。

所以我的问题是,为什么会有区别?SQL Mgmt Studio的锁定方式可能与控制台应用程序不同吗?

这种行为通常源于从ADO.NET和SSMS获得不同的执行计划。这是因为执行计划不仅必须考虑SQL本身,还必须考虑ANSI_NULLS、ARITHABORT和其他几种设置形式的上下文。因此,如果这些设置不相同,则不能在另一个环境中使用来自一个环境的执行计划。

使用默认设置,除了ARITHABORT之外,SSMS和ADO.NET中的一切都是一样的。这在ADO.NET中设置为OFF,在SSMS中设置为ON,因此要获得与应用程序相同的缓存查询计划,您需要在SSMS中将ARITHABORT设置为OFF。现在,您应该可以在SSMS中看到与应用程序调用中相同的性能。在这篇漂亮的博客文章中查看更多背景信息:http://www.sommarskog.se/query-plan-mysteries.html

如果您的查询返回了大量数据,还有另一个因素,因为默认情况下,SSMS会读取所有这些数据,并在完成和显示总查询时间之前将其显示出来。它读取它的速度取决于您在服务器本地或远程执行SSMS的位置。在远程情况下,数据必须通过网络传输,这通常比本地呼叫慢。通常情况下,测量传输时间是可以的,因为您的应用程序也是这样做的。然而,SSMS也显示数据,这可能比实际加载数据花费更长的时间。为了防止这种情况,您可以通过"工具"->"选项"->"查询结果"->"SQL Server"->"结果到网格"->"执行后丢弃结果"禁用SSMS中的数据显示。

如果仍然有不同的行为,请通过SQL事件探查器捕获执行计划并进行比较。

我去年也遇到过类似的问题。尝试在存储过程中启用arithaport:在上设置arithabort

摘自msdn

SQL Server Management Studio的默认ARITHABORT设置为ON。将ARITHABORT设置为OFF的客户端应用程序可能会收到不同的查询计划,从而难以解决性能不佳的查询也就是说,相同的查询在management studio中执行速度很快,但在应用程序中执行速度较慢使用Management Studio对查询进行故障排除时,始终与客户端ARITHABORT设置相匹配。

最新更新