SqlDataAdapter.Fill方法慢
为什么在SQL Server Management Studio中运行需要<1秒时,使用此代码返回一个包含9列,89行的表的存储过程需要60秒才能执行(.NET 1.1)? 它在本地机器上运行很less/没有networking延迟,快速开发机器
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]
首先,确保你正确地分析性能。 例如,从ADO.NET运行查询两次,查看第二次是否比第一次快得多。 这消除了等待应用程序编译和debugging基础设施增加的开销。
接下来,检查ADO.NET和SSMS中的默认设置。 例如,如果您在SSMS中运行SET ARITHABORT OFF,则可能会发现它现在运行速度与使用ADO.NET时一样慢。
我曾经发现,SSMS中的SET ARITHABORT OFF导致存储过程被重新编译和/或使用不同的统计数据。 突然,SSMS和ADO.NET报告的执行时间大致相同。
要检查这个,查看每个运行的执行计划,特别是syscacheobjects表。 他们可能会有所不同。
在特定的存储过程上运行“sp_recompile”会将关联的执行计划从caching中删除,这样SQL Server就有机会在下一次执行过程时创build一个更合适的计划。
最后,你可以尝试使用SSMS清除整个过程caching和内存缓冲区的“ nuke it from轨道 ”方法:
DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE
在testing查询之前这样做会阻止使用caching的执行计划和以前的结果caching。
这是我最终做的:
我执行了下面的SQL语句来重build数据库中所有表上的索引:
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"
我遇到了同样的问题,但是当我在SQL表上重build索引,它工作正常,所以你可能要考虑在SQL Server端重build索引
为什么不使用DataReader而不是DataAdapter,它看起来像你有一个singel结果集,如果你不打算推回在数据库中的变化,并不需要在.NET代码中应用的约束,你不应该使用适配器。
编辑:
如果你需要它是一个DataTable,你仍然可以通过DataReader从数据库中获取数据,然后在.NET代码中使用DataReader来填充一个DataTable。 这应该仍然比依靠DataSet和DataAdapter更快
我有同样的问题,并得到了解决使用这篇文章: http : //www.databasejournal.com/features/mssql/article.php/3841271/T-SQL-Best-Practices–Parameter-Sniffing.htm
我不知道“为什么”这本身就是如此之慢 – 但正如马库斯所指出的那样 – 比较pipe理工作室和填充数据集的方法是苹果橙子。 数据集包含很多开销。 我恨他们,永远不要使用他们,如果我能帮助它。
你可能会遇到与旧版本的SQL堆栈不匹配的问题或一些这样的问题(特别是你显然被困在.NET 1.1中)。框架可能试图做“reflection”的数据库equivilant来推断模式等等等等
有一件事要考虑尝试一下你的不幸的约束,就是用datareader访问数据库,并用代码构build你自己的数据集。 你应该能够通过谷歌轻松find样本。