这是我在另一个论坛上提出的问题,得到了一些不错的答案,但我想看看这里是否有人有更多的见解。

问题是,您的 Web 应用程序中的一个页面在调用存储过程时超时,因此您使用 Sql Profiler 或应用程序跟踪日志来查找查询,然后将其粘贴到 Management Studio 中来计算我们为什么它运行缓慢。但你从那里运行它,它就会一直燃烧,每次返回不到一秒钟。

我的具体情况是使用 ASP.NET 2.0 和 Sql Server 2005,但我认为该问题可能适用于任何 RDBMS 系统。

有帮助吗?

解决方案

这是我迄今为止从研究中了解到的。

.NET 发送的连接设置与您登录 Management Studio 时获得的连接设置不同。如果您使用 Sql Profiler 嗅探连接,您会看到以下内容:

-- network protocol: TCP/IP  
set quoted_identifier off  
set arithabort off  
set numeric_roundabort off  
set ansi_warnings on  
set ansi_padding on  
set ansi_nulls off  
set concat_null_yields_null on  
set cursor_close_on_commit off  
set implicit_transactions off  
set language us_english  
set dateformat mdy  
set datefirst 7  
set transaction isolation level read committed  

我现在将这些设置粘贴到登录 sql server 时运行的每个查询上方,以确保设置相同。

对于这种情况,我在断开连接并重新连接后单独尝试了每个设置,发现将 arithabort 从关闭更改为打开将问题查询从 90 秒缩短到 1 秒。

最可能的解释与参数嗅探有关,参数嗅探是 Sql Server 用于选择它认为最有效的查询计划的技术。当您更改其中一项连接设置时,查询优化器可能会选择不同的计划,在这种情况下,它显然选择了一个错误的计划。

但我并不完全相信这一点。我尝试比较更改此设置后的实际查询计划,但尚未看到差异显示任何更改。

在某些情况下,arithabort 设置是否还有其他问题可能导致查询运行缓慢?

解决方案看起来很简单:只需将 set arithabort on 放入存储过程的顶部即可。但这可能会导致相反的问题:更改查询参数,“off”突然比“on”运行得更快。

目前,我正在运行“重新编译”过程,以确保每次都能重新生成计划。对于这个特定的报告来说还好,因为重新编译可能需要一秒钟,而对于需要 1-10 秒返回的报告(这是一个怪物),这并不太明显。

但对于运行更频繁并且需要尽快返回(只需几毫秒)的其他查询来说,这不是一个选择。

其他提示

我也遇到过类似的问题。尝试在 sproc create 上设置 with “WITH RECOMPILE” 选项,以强制系统在每次调用时重新计算执行计划。有时,查询处理器会在具有大量分支或 case 语句的复杂存储过程中感到困惑,并且只会提取真正次优的执行计划。如果这似乎“解决”了问题,您可能需要验证统计信息是否是最新的和/或分解存储过程。

您还可以通过分析存储过程来确认这一点。当您从 SQL Managment Studio 执行它时,IO 与您从 ASP.NET 应用程序中分析它时相比如何。如果它们太多,它只会再次强化其执行计划的糟糕性。

您打开 ASP.NET 跟踪了吗?我遇到过一个实例,问题不是 SQL 存储过程本身,而是该过程返回 5000 行,并且应用程序试图使用这 5000 个项目创建数据绑定 ListItems,从而导致了问题。

您还可以通过跟踪来查看 Web 应用程序函数之间的执行时间,以帮助跟踪情况。

首先在暂存盒上进行测试,然后在 sql server 的服务器级别上更改它

声明@option int

设置@option = @@选项| 64

exec sp_configure'用户选项',@option

重新配置

我在使用 SQL 报告服务时也遇到同样的问题。尝试检查变量的类型,我将不同类型的变量发送到SQL,例如将VARCHAR发送到适当的位置,该变量应该是整数或类似的东西。在我同步了 Reporting Service 中的变量类型和 SQL 上的存储过程中的变量类型后,我解决了这个问题。

您可以尝试使用 sp_who2 命令来查看有问题的进程正在做什么。这将向您显示它是否被另一个进程阻塞,或者使用过多的 cpu 和/或 io 时间。

我们遇到了同样的问题,这就是我们发现的情况。

我们的数据库日志大小保持默认值 (814 MB),自动增长为 10%。在服务器上,最大服务器内存也保留为默认设置 (2147483647 MB​​)。

当我们的日志已满并需要增长时,它会使用服务器中的所有内存,并且没有剩余空间可供代码运行,因此超时。我们最终所做的是将数据库日志文件初始大小设置为 1 MB,将最大服务器内存设置为 2048 MB。这立即解决了我们的问题。当然,您可以更改这两个属性来满足您的需要,但这对于通过代码执行存储过程时遇到超时问题的人来说是一个想法,但它在 SSMS 中运行速度非常快,并且上面的解决方案没有帮助。

尝试更改 SelectCommand 超时值:

DataAdapter.SelectCommand.CommandTimeout = 120;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top