2013-02-04 58 views
1

我有一个存储过程正在执行INSERT语句,我们在执行时看到显着的延迟。当从我们的C#.NET应用程序运行它以在一行中插入30条记录时,总共需要大约4秒才能完成(只计算运行SqlCommand.ExecuteNonQuery()方法所需的时间)。但是,从SQL Server Management Studio中调用相同的确切存储过程的次数只需要大约0.4秒。我无法弄清楚这两种设置之间会有10倍速度的差别。存储过程在.NET SqlCommand中比在SSMS中慢很多

我已经尝试了所有与速度无明显变化如下:

  1. 创建存储过程“WITH RECOMPILE”
  2. 检查所有正在内SSMS和C#配置的“设置”值的。唯一的区别是SET ARITHABORT,它在.NET应用程序中调用时处于SSMS状态,处于OFF状态。不过,将“SET ARITHABORT ON”添加到存储过程的开始并没有什么区别。
  3. 从存储过程中移除所有的默认值的参数

用于从.NET应用程序调用存储过程中的代码是:

using (SqlConnection newConn = new SqlConnection(connectionString)) 
{ 
    using (SqlCommand uCmd = new SqlCommand("sproc_name", newConn)) 
    { 
     uCmd.CommandType = CommandType.StoredProcedure; 
     uCmd.Connection.Open(); 

     //About 15 parameters added using: 
     uCmd.Parameters.AddWithValue("@ParamName", value); 
     ... 

     //One output parameter 
     SqlParameter paramOUT = new SqlParameter("@OutPutKey", SqlDbType.UniqueIdentifier); 
     paramOUT.Direction = ParameterDirection.Output; 
     uCmd.Parameters.Add(paramOUT); 

     uCmd.ExecuteNonQuery(); 
     uCmd.Connection.Close(); 
    } 
} 

存储过程本身只是一组命令的列表(SET ANSI_NULLS ON,SET QUOTED_IDENTIFIER ON,SET ARITHABORT ON),非默认参数列表以及输出变量的设置,该变量将成为将作为主键插入到表中的新唯一标识符,然后是INSERT语句本身。

的应用是建立在.NET 4和SQL服务器是MS SQL Server 2005中

这里是插入存储过程中它调用的一个例子:

alter procedure InsertStuff 
@Field1 uniqueidentifier, 
@Field2 datetime, 
... 
@CreateDate datetime, 
@PrimaryKEY uniqueidentifier OUTPUT 
AS 

declare @newCreateDate datetime 
set @newCreateDate=getDate() 

set @PrimaryKEY = NEWID() 

INSERT INTO [dbo].[Table] 
(
    Field1, 
    Field2, 
    ... 
    CreateDate, 
    PrimaryKEY 
) 
VALUES 
(
    @Field1, 
    @Field2, 
    ... 
    @newCreateDate, 
    @PrimaryKEY 
) 
+6

没有看到存储过程很难回答, 听起来,你在调用这个方法30次,但从你的代码打开和关闭,处理连接30次。保持连接打开,然后调用存储过程30次。 – Peter

+1

也只是设置一次命令,只是为每个调用添加参数值 –

+0

这个问题可能会帮助http://stackoverflow.com/questions/801909 – devio

回答

2

有可能的问题是,每个执行命令调用都会执行一次网络跳转,其中ssms将一次批量发送全部30个命令到服务器。我相信默认情况下,SSMS会将所有30条语句作为一个批次发送,但是如果您更改了可能影响事件的其他设置。

此外,请确保您每次都不打开和关闭连接。尽管连接池可能不会成为问题,但我不会放弃。

+1

连接池不会使其成为非问题,因为重新使用池连接仍会导致额外的往返行为,因为在同一连接上为连接重新设置新的“会话”。 “SSMS将会批量发送所有30个命令”,真正解决SSMS测试的问题(在一个批次中循环,或者30个独立批次) - 你是对的,为了比较苹果和苹果, SSMS测试应实施为30批次,用“GO”批分离器分隔。 – Tao

+0

@Tao是的,有一些重置可能会完成(我实际上已经听说池的连接有意外的设置,如不同的超时,所以我不知道实际重置了多少)。建立连接通常比发送命令更昂贵,但我明白你的观点。这实际上取决于“重置”完成了多少。我已经更新了我的答案,希望能够更清楚地表明我正在假设SSMS的默认设置。 – Andy

+0

所以事实证明,我的测试环境已经搞砸了,实际上,从.NET和SSMS调用此插入存储过程的速度大致相同。但是,我正在考虑共享单个SqlConnection和单个SqlCommand(在至少调用相同存储过程的情况下)。这给了我大约25%的节省速度。不过,我仍然认为它应该能够比这更快地完成这些插入操作。我添加了一个插入存储过程的示例。你看到有其他需要改进的空间吗? – Rett

相关问题