14

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

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

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

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

这是使用 C#.NET。数据库是 MS SQL Server 2012。

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

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

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

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

通过这种方式,我们可以看到在 SQL 上花费了多少时间与整体相比,其中 99% 的时间都花在了 SQL 上。

但是如果在 SQL Mgmt Studio 中也不是很慢,就很难调试和改进。

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

4

2 回答 2

13

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

在默认设置下,SSMS 和 ADO.NET 中的所有内容都相同,除了 ARITHABORT。这在 ADO.NET 中设置为 OFF,在 SSMS 中设置为 ON,因此要获得与应用程序相同的缓存查询计划,您需要在 SSMS 中设置 ARITHABORT OFF。现在您应该在 SSMS 中看到与来自应用程序的调用相同的性能。在这篇不错的博客文章中查看更多背景信息:http: //www.sommarskog.se/query-plan-mysteries.html

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

如果您仍然得到不同的行为,请通过 SQL Profiler 捕获执行计划并进行比较。

于 2013-06-28T13:36:51.100 回答
9

去年我也有类似的问题。尝试在存储过程中启用 arithabort:SET ARITHABORT ON

摘自msdn

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

于 2013-06-28T13:01:39.350 回答