我有一个正在执行的旧版ASP.NET WebForms应用程序正在执行的存储过程。 CommandTimeout
属性已设置为6分钟。存储过程查询一个包含1500万行的表并连接到其他表....所以它很慢。但是,它只返回20行,因此网络性能不是问题。
var data = new DataSet();
using (var connection = GetConnection())
using(var command = connection.CreateCommand())
using(var dataAdapter = new SqlDataAdapter(command))
{
command.CommandTimeout = 360;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "praGetTradesForProductIdReassignment";
command.Parameters.AddWithValue("@int4_TradeId", (object)tradeId ?? DBNull.Value);
command.Parameters.AddWithValue("@int4_FeedId", (object)feedId ?? DBNull.Value);
command.Parameters.AddWithValue("@int4_SystemId", (object)systemId ?? DBNull.Value);
command.Parameters.AddWithValue("@int4_TradeCode", (object)tradeCode ?? DBNull.Value);
command.Parameters.AddWithValue("@int4_ProductID", (object)productId ?? DBNull.Value);
command.Parameters.AddWithValue("@sortColumn", sortColumn);
command.Parameters.AddWithValue("@sortDirection", sortDirection);
command.Parameters.AddWithValue("@pageIndex", pageIndex);
command.Parameters.AddWithValue("@pageSize", pageSize);
dataAdapter.Fill(data);
}
return data;
当我使用SQL Server Management Studio中的相同参数执行相同的存储过程时,它会在大约50秒后成功完成。
我使用Profiler运行SQL跟踪,显示ADO.NET执行时间比SQL Server Management Studio执行时间长(50 vs 356秒)。
<Events>
<Event id="13" name="SQL:BatchStarting">
<Column id="1" name="TextData">exec praGetTradesForProductIdReassignment @int4_TradeId=NULL,@int4_FeedId=NULL,@int4_SystemId=NULL,@int4_TradeCode=NULL,@int4_ProductID=NULL,@sortColumn=N'',@sortDirection=0,@pageIndex=0,@pageSize=20</Column>
<Column id="10" name="ApplicationName">Microsoft SQL Server Management Studio - Query</Column>
</Event>
<Event id="12" name="SQL:BatchCompleted">
<Column id="10" name="ApplicationName">Microsoft SQL Server Management Studio - Query</Column>
<Column id="1" name="TextData">exec praGetTradesForProductIdReassignment @int4_TradeId=NULL,@int4_FeedId=NULL,@int4_SystemId=NULL,@int4_TradeCode=NULL,@int4_ProductID=NULL,@sortColumn=N'',@sortDirection=0,@pageIndex=0,@pageSize=20</Column>
<Column id="13" name="Duration">49946289</Column>
</Event>
<Event id="10" name="RPC:Completed">
<Column id="10" name="ApplicationName">.Net SqlClient Data Provider</Column>
<Column id="1" name="TextData">exec praGetTradesForProductIdReassignment @int4_TradeId=NULL,@int4_FeedId=NULL,@int4_SystemId=NULL,@int4_TradeCode=NULL,@int4_ProductID=NULL,@sortColumn=N'',@sortDirection=0,@pageIndex=0,@pageSize=20</Column>
<Column id="13" name="Duration">356352721</Column>
</Event>
</Events>
为什么ADO.NET执行所需的时间比SSMS执行的时间长得多?
这个问题的目的不是为了提高存储过程的性能,而是为了确定通过ADO.NET与SSMS进行调用之间性能差异的原因。
答案 0 :(得分:6)
首先,重要的是要知道ADO.NET和SSMS(SQL Server Management Studio)是不同的实体。因此,您应该考虑查询执行中存在某些行为/操作变化。
第1部分:为什么SQL查询在SSMS中的运行速度比ADO.NET快?
在SSMS中运行任何查询时,它始终会为其创建查询计划。查询计划通过各种优化以及搜索结果的索引来执行。您可以想象在此过程中涉及某种缓存。
此外,当Microsoft开发SSMS和ADO.NET时,并非所有参数都相同。您会发现ANSI_NULLS,ARITHABORT等参数的设置与针对ADO.NET的SSMS中的设置不同
如果您想确保您的SQL Query执行是按照SSMS本身执行的,请确保两种情况下的设置都相同。
第2部分:你能尝试什么?
有几种方法可以尝试解决问题。
启用ARITHABORT参数 :ATITHABORT的设置与ADO.NET&amp; SSMS。您可以尝试在查询中启用ARITHABORT并执行。
SET ARITHABORT ON
启用ANSI_NULLS :在查询文本中将ANSI_NULLS的设置更改为“已启用”。
SET ANSI_NULLS ON
以类似的方式,您可以在SSMS和ADO.NET中进行设置,从而产生非常接近的执行结果。
第3部分:参数嗅探
最后但并非最不重要,了解查询结构也很重要。您可以通过使用存储过程中的局部变量来优化SQL查询,尽可能使用游标等。
第4部分:参考资料
希望它有所帮助......一切顺利!!