从代码运行时存储过程超时,但不从查询工具运行

时间:2010-08-03 15:58:03

标签: c# sql-server stored-procedures

我试图弄清楚为什么存储过程调用在SQL Server express查询窗口中需要几秒钟,但是当我运行时,在代码中调用存储过程查询TIMES OUT。我们正在使用sql server 2008.我知道很难在没有看到存储过程的情况下确切地说明发生了什么。我只是希望这是一个已知的问题。非常感谢任何指导。

调用“STORED_PROCEDURE_X”并在SQL Server express查询窗口中运行2秒的SQL查询:

EXEC STORED_PROCEDURE_X '07/01/2010', '07/31/2010', 0, '', 'true','', 'Top 20'

调用“STORED_PROCEDURE_X”和TIMES OUT的代码:

SqlConnection connSQL = null;
SqlCommand sqlCmd = null;
SqlDataAdapter sqlDataAdpater = null;
DataTable returnData = null;

try
{
    returnData = new DataTable();
    connSQL = new SqlConnection(sqlConnection);
    sqlCmd = new SqlCommand("STORED_PROC_X", connSQL);
    if (connSQL.State == ConnectionState.Closed)
    {
        connSQL.Open();
    }
    sqlCmd.CommandType = CommandType.StoredProcedure;
    sqlCmd.CommandTimeout = 600;
    sqlCmd.Parameters.Add("@StartDate", SqlDbType.NVarChar).Value = "07/01/2010";
    sqlCmd.Parameters.Add("@EndDate", SqlDbType.NVarChar).Value = "07/31/2010";

    sqlCmd.Parameters.Add("@AuditType", SqlDbType.Int).Value = "0";

    sqlCmd.Parameters.Add("@SortBy", SqlDbType.NVarChar).Value = "";

    sqlCmd.Parameters.Add("@IsClaimDepartment", SqlDbType.NVarChar).Value = "true";
    sqlCmd.Parameters.Add("@IdsList", SqlDbType.NVarChar).Value = "";
    sqlCmd.Parameters.Add("@ReportType", SqlDbType.NVarChar).Value = "Top 20";
    sqlDataAdpater = new SqlDataAdapter(sqlCmd);
    sqlDataAdpater.Fill(returnData);
    if (connSQL.State == ConnectionState.Open)
    {
        connSQL.Close();
    }
    return returnData;
}
catch (Exception ex)
{
    LogErrorMessages("ExecuteStoredProcedure", ex.Message);
    throw ex;
}

收到异常:

System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.

11 个答案:

答案 0 :(得分:10)

所以,运行一个返回30条记录的存储过程在管理控制台中花了我00:00秒,但是当它加载到.net时花了我大约40秒,超过了默认的30秒TimeOut。

我只修改存储过程并重新运行ALTER PROCEDURE ...代码而不更改任何内容,问题立即得到解决。我没有关于此错误来源的更多详细信息,但至少它是一个非常快速的解决方案

答案 1 :(得分:4)

对我来说总是很有帮助的是在程序中添加“ with recompile ”选项。

http://technet.microsoft.com/en-us/library/ms190439.aspx

答案 2 :(得分:3)

假设您在代码中传递与在SSMS中测试时相同的参数,并且您的SSMS测试在数据类型使用方面完全相同,我认为这可能是参数嗅探问题。

您是否可以访问SQL Profiler(不附带Express版本)来获取实际的执行计划?如果没有,您可以按照in this answer的建议来制定计划。

答案 3 :(得分:2)

我遇到类似的问题,存储过程比查询窗口中的同一查询运行得慢。 我已经尝试了编码参数嗅探(局部变量),删除聚簇索引和仅使用非聚集等等所有内容。使用nvarchar参数检索varchar字段仍需要22秒。

我原本以为只是nvarchar和varchar之间的区别,并将数据库字段更改为nvarchar。我又丢了一整天,将5000万条记录转移到新表并重新编制索引。仍然花了超过22秒。

最后,我将表中的任何关键字段从nvarchar更改为varchar,加上所有参数和哇;回到不到1秒。

我坚信这是SQL Server中的一个错误,从未得到纠正。如何直接在查询窗口中运行查询,或者从vb.net或c#代码调用sql并在不到1秒的时间内获得结果;然后在存储过程中使用参数运行相同的查询并得到这样的horrendus结果?

简短回答:不惜一切代价远离nvarchar数据类型。

另外,学习使用merge语句将数据移动到大表中以避免超时。 将恢复模式设置为简单,同时运行大型合并查询;然后恢复完全恢复。

男孩,本周我学到了很多东西。超过80小时的教育,我不需要。 但是,LinkToMeet.com现在有超过1.5亿会员,一切都很好。

答案 4 :(得分:1)

尝试a)重新组织代码,b)增加超时时间:

DataTable returnData = null;

try
{
    using(SqlConnection connSQL = new SqlConnection(sqlConnection))
    using(SqlCommand sqlCmd = new SqlCommand("STORED_PROC_X", connSQL))
    {
       sqlCmd.CommandType = CommandType.StoredProcedure;
       sqlCmd.CommandTimeout = 1200;

       // those two parameters should really be SqlDbType.DateTime!!
       sqlCmd.Parameters.Add("@StartDate", SqlDbType.NVarChar, 25).Value = "07/01/2010";
       sqlCmd.Parameters.Add("@EndDate", SqlDbType.NVarChar, 25).Value = "07/31/2010";

       sqlCmd.Parameters.Add("@AuditType", SqlDbType.Int).Value = "0";

       sqlCmd.Parameters.Add("@SortBy", SqlDbType.NVarChar, 50).Value = "";

       // this parameter should really be SqlDbType.Bit !!
       sqlCmd.Parameters.Add("@IsClaimDepartment", SqlDbType.NVarChar, 50).Value = "true";

       sqlCmd.Parameters.Add("@IdsList", SqlDbType.NVarChar, 25).Value = "";
       sqlCmd.Parameters.Add("@ReportType", SqlDbType.NVarChar, 25).Value = "Top 20";

       SqlDataAdapter sqlDataAdpater = new SqlDataAdapter(sqlCmd);

       returnData = new DataTable();
       sqlDataAdpater.Fill(returnData);
   }

   return returnData;
}
catch (Exception ex)
{
   LogErrorMessages("ExecuteStoredProcedure", ex.Message);
   throw;
}

SqlDataAdapter将打开和关闭连接本身 - 无需明确地执行此操作。

此外,我会

  • 为您的NVARCHAR参数定义合理的最大长度(除了存储的proc之外)
  • 将日期传递为 DATETIME ! (不是NVARCHAR)
  • 将布尔值传递为 BIT ! (不是NVARCHAR)
  • 当你重新抛出异常时,只使用throw而不是throw ex(如果你使用throw ex,你基本上打破了堆栈跟踪,无法弄清楚异常的位置真的来自)

答案 5 :(得分:1)

确保传递给SP的参数与数据库中的参数匹配[这是区分大小写]

答案 6 :(得分:0)

您是否在存储过程中使用任何事务?未提交的事务将导致此确切的错误消息。

答案 7 :(得分:0)

I had same issue. My stored proc executed from MSSMS or dbForgeStudio, but not from C# code (SqlCommand). I fixed this problem by altering stored proc in SQL server (without any changes).

答案 8 :(得分:0)

我尝试使用“ with recompile”,“ arithabort off”,更改代码等,但最后仅重新启动sql server即可解决问题。

答案 9 :(得分:0)

我们遇到了同样的问题,并认为它也是参数嗅探,但是在尝试了许多事情之后,包括更改参数嗅探,与重新编译一起使用,删除/重新创建,更新统计信息,释放proc缓存,我们发现这些都不起作用。我们将其跟踪到需要添加的单个索引。我们刚刚从传统基数估算器切换到2014年后估算器。切换回旧的估算器可以解决此问题,或者使用新的估算器并添加索引。

答案 10 :(得分:-1)

更改CommandTimeout = 0

sqlCmd.CommandTimeout = 0;