为什么在SQL Server Management Studio中运行<1秒时,使用此代码返回具有9列,89行的表的存储过程需要60秒才能执行(.NET 1.1)?它在本地计算机上运行,因此很少/没有网络延迟,快速开发机器
Dim command As SqlCommand = New SqlCommand(procName, CreateConnection()) command.CommandType = CommandType.StoredProcedure command.CommandTimeout = _commandTimeOut Try Dim adapter As new SqlDataAdapter(command) Dim i as Integer For i=0 to parameters.Length-1 command.Parameters.Add(parameters(i)) Next adapter.Fill(tableToFill) adapter.Dispose() Finally command.Dispose() End Try
我的参数数组是打字的(对于这个SQL,它只是一个参数)
parameters(0) = New SqlParameter("@UserID", SqlDbType.BigInt, 0, ParameterDirection.Input, True, 19, 0, "", DataRowVersion.Current, userID)
存储过程只是一个select语句,如下所示:
ALTER PROC [dbo].[web_GetMyStuffFool] (@UserID BIGINT) AS SELECT Col1, Col2, Col3, Col3, Col3, Col3, Col3, Col3, Col3 FROM [Table]
RoadWarrior.. 47
首先,确保正确分析性能.例如,从ADO.NET运行两次查询,看看第二次是否比第一次快得多.这消除了等待应用程序编译和调试基础架构升级的开销.
接下来,检查ADO.NET和SSMS中的默认设置.例如,如果在SSMS中运行SET ARITHABORT OFF,您可能会发现它现在运行速度与使用ADO.NET时一样慢.
我曾经发现的是SSMS中的SET ARITHABORT OFF导致重新编译存储过程和/或使用不同的统计信息.突然间,SSMS和ADO.NET都报告了大致相同的执行时间.
要检查这一点,请查看每次运行的执行计划,特别是syscacheobjects表.他们可能会有所不同.
在特定存储过程上运行"sp_recompile"将从缓存中删除关联的执行计划,从而使SQL Server有机会在下次执行该过程时创建可能更合适的计划.
最后,您可以尝试使用SSMS清除整个过程缓存和内存缓冲区的" 从轨道上进行核武器 "方法:
DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE
在测试查询之前执行此操作可防止使用缓存的执行计划和先前的结果缓存.
首先,确保正确分析性能.例如,从ADO.NET运行两次查询,看看第二次是否比第一次快得多.这消除了等待应用程序编译和调试基础架构升级的开销.
接下来,检查ADO.NET和SSMS中的默认设置.例如,如果在SSMS中运行SET ARITHABORT OFF,您可能会发现它现在运行速度与使用ADO.NET时一样慢.
我曾经发现的是SSMS中的SET ARITHABORT OFF导致重新编译存储过程和/或使用不同的统计信息.突然间,SSMS和ADO.NET都报告了大致相同的执行时间.
要检查这一点,请查看每次运行的执行计划,特别是syscacheobjects表.他们可能会有所不同.
在特定存储过程上运行"sp_recompile"将从缓存中删除关联的执行计划,从而使SQL Server有机会在下次执行该过程时创建可能更合适的计划.
最后,您可以尝试使用SSMS清除整个过程缓存和内存缓冲区的" 从轨道上进行核武器 "方法:
DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE
在测试查询之前执行此操作可防止使用缓存的执行计划和先前的结果缓存.
这是我最终做的事情:
我执行了以下SQL语句来重建数据库中所有表的索引:
EXEC..sp_MSforeachtable @command1='DBCC DBREINDEX (''*'')', @replacechar='*' -- Replace with the name of your database
如果我想在SSMS中看到相同的行为,我就像这样运行proc:
SET ARITHABORT OFF EXEC [dbo].[web_GetMyStuffFool] @UserID=1 SET ARITHABORT ON
绕过这个的另一种方法是将其添加到您的代码中:
MyConnection.Execute "SET ARITHABORT ON"