存储过程在.NET SqlCommand中比在SSMS中慢得多

时间:2013-02-04 22:27:15

标签: c# .net sql ssms

我有一个正在执行INSERT语句的存储过程,我们在执行时看到了很大的延迟。当从我们的C#.NET应用程序运行它以连续插入30条记录时,它总共花费大约4秒来完成(仅计算运行SqlCommand.ExecuteNonQuery()方法所需的驯服)。但是,从SQL Server Management Studio中调用相同的存储过程相同的次数只需要大约0.4秒。我无法弄清楚两种设置之间的差异会产生10倍速的差异。

我尝试了以下所有方面,速度没有明显变化:

  1. 创建存储过程“WITH RECOMPILE”
  2. 检查在SSMS和C#中配置的所有“SET”值。唯一的区别是SET ARITHABORT,它在SSMS中为ON,从.NET应用程序调用时为OFF。但是,将“SET ARITHABORT ON”添加到存储过程的开头没有任何区别。
  3. 从sproc参数
  4. 中删除了所有默认值

    用于从.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命令(SET ANSI_NULLS ON,SET QUOTED_IDENTIFIER ON,SET ARITHABORT ON),一个非默认参数列表,以及将成为新uniqueidentifier的输出变量的设置。将作为主键插入表中,然后是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
    ) 
    

1 个答案:

答案 0 :(得分:2)

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

此外,请确保每次都不打开和关闭连接。虽然连接池可能会成为一个非问题,但我不会把它留给机会。