2008-10-30 94 views
30

为什么存储过程返回一个包含9列的表,使用此代码的89行需要60秒才能执行(.NET 1.1),这需要在SQL Server Management Studio中运行1秒钟的时间?它被在本地机器上运行,因此很少/没有网络延迟,快速dev的机器SqlDataAdapter.Fill方法缓慢

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] 
+0

这是一个古老的问题,许多人找到它。在开始清理缓存并使用ARITHABORT设置进行游戏之前,请阅读Erland Sommarskog的综合文章,该文章解释了可能发生的情况:[缓慢的应用程序,SSMS中的快速?了解性能之谜](http://www.sommarskog.se/query-plan-mysteries.html)很多时候,这种行为是由称为“参数嗅探”的SQL Server功能引起的。 – 2016-05-26 23:59:07

回答

45

首先,确保您正确分析性能。例如,从ADO.NET运行查询两次,查看第二次是否比第一次快得多。这消除了等待应用程序编译和调试基础架构增加的开销。

接下来,检查ADO.NET和SSMS中的默认设置。例如,如果您在SSMS中运行SET ARITHABORT OFF,则可能会发现它现在运行速度与使用ADO.NET时相比较慢。

我发现一次是SSMS中的SET ARITHABORT OFF导致存储过程被重新编译和/或使用不同的统计数据。突然,SSMS和ADO.NET报告的执行时间大致相同。

要检查这一点,请查看每次运行的执行计划,尤其是syscacheobjects表。他们可能会有所不同。

在特定的存储过程上运行'sp_recompile'将从缓存中删除相关的执行计划,这使SQL Server有机会在下一次执行过程时创建一个可能更合适的计划。

最后,你可以使用SSMS尝试清理整个过程高速缓存和内存缓冲区的“nuke it from orbit”的方法:

DBCC DROPCLEANBUFFERS 
DBCC FREEPROCCACHE 

这样做你测试你的查询之前,防止高速缓存的执行计划和之前的结果用法缓存。

+2

DBCC DROPCLEANBUFFERSDBCC FREEPROCCACHE解决了我的问题。这是否需要定期运行,或只有在对存储过程进行更改时才运行? – Merritt 2009-08-13 17:59:07

+2

这是一个循环的基础,因为这些缓存的结果和计划将逐渐积累。 – RoadWarrior 2009-09-15 14:52:27

1

为什么不把它一个DataReader,而不是DataAdapter的,它看起来像你有一个辛格运河结果集,如果你不打算要推动改变BAC k,并且不需要在.NET代码中应用约束,则不应使用适配器。

编辑:

如果你需要的是一个DataTable你仍然可以通过一个DataReader拉从数据库中的数据,然后在.NET代码使用DataReader来填充的DataTable。这应该仍然比依靠数据集和DataAdapter更快

+0

我正在使用的代码无法返回除此数据表以外的任何其他内容。 – 2008-10-30 16:16:46

0

我不知道“为什么”它本身就很慢 - 但正如马库斯指出的那样 - 比较Mgmt Studio和填充数据集的结果是橙子。数据集包含很多开销。我讨厌他们,如果我能帮到他们,永远不要使用他们。

您可能会遇到SQL堆栈旧版本的不匹配问题或某些此类问题(特别是您明显陷于.NET 1.1中)该框架可能会尝试执行数据库“反射”的平等性来推断模式等等等等

有一件事要考虑尝试与你的不幸的约束是访问与datareader数据库,并在代码中建立自己的数据集。你应该能够通过谷歌轻松找到样本。

+0

并请使用一些使用语句,因为您的连接实现了IDisposable – 2009-01-29 18:42:35

4

这里是我落得这样做:

我执行下面的SQL语句来重建对数据库中的所有表的索引:

EXEC <databasename>..sp_MSforeachtable @command1='DBCC DBREINDEX (''*'')', @replacechar='*' 
-- Replace <databasename> 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" 
2

我遇到了同样的问题,但是当我重建了SQL表的索引,它工作得很好,所以你可能要考虑在sql server端重建索引