每次迭代相同的SPROC时,执行时间会变慢

时间:2012-04-11 20:15:05

标签: c# .net sql-server performance connection-pooling

通过网络从C#.Net应用程序运行相同存储过程会随着每次后续执行而逐渐变慢。它似乎需要两次与前一次执行相比的时间量(达到最大值;继续阅读)。执行时间逐渐变慢,直到2个场景中的1个发生,此时SPROC的第一次执行再次“快速”。

  1. 如果SqlConnection打开并在所有测试期间保持打开状态, 在运行任何其他 SPROC 或查询之前,SPROC会逐渐变慢。
  2. 如果在每次执行时打开并关闭SqlConnection,则 SPROC逐渐变慢,直到至少8分钟过去。
  3. 只有少数存储过程才会发生这种情况。一个是简单的SELECT查询,其中包含2个JOINs,( SPROC 1 ),另一个是大规模的1600多行SPROC( SPROC 2 )。< / p>

    SPROC 1 的执行时间似乎永远不会超过60秒, SPROC 2 的执行时间似乎超过67秒。 SPROC 1 最初执行时间不到一秒, SPROC 2 最初需要7秒。

    只有在应用程序中使用相同的SqlConnection运行SPROC时,才会发生这种情况。一旦使用了2个单独的SqlConnection个对象,它们的行为与上述相同,但它们是独立的。在SqlConnection1上多次运行SPROC会逐渐变慢,但第一次在SqlConnection2上运行相同的SPROC时,它会“快速”。在SqlConnection2上多次运行时,它也会变慢。

    如果应用程序在安装了SQL Server 2008 R2的同一台计算机上运行(运行Windows Server 2008),则不会发生这种情况。执行时间总是一致的。

    每次执行时,从Management Studio中运行存储过程也不会变慢;它总是一致的。

    清除执行计划缓存(在SQL Server中)对观察到的行为没有影响。

    为了创建一个测试应用程序以轻松测试/重现它,需要花费相当多的时间来缩小最初在更大的应用程序中观察到的这个问题。

    从我读过here开始,超时时间在4到8分钟之间(在代码中调用SqlConnection.Close()之后),此时它会关闭与数据源的数据库连接。这似乎与我上面提到的情景2一致。

    这让我相信它与使用的SqlConnection(以及与数据源的底层数据库连接)有关,因为在我的情况下启用了连接池,但是为什么我会观察到这种行为,以及如何解决?

    我们正在使用.Net 2.0 Framework,如果这有任何区别的话。

    上面列出了许多细节,如果我需要澄清任何内容,请告诉我。

    唯一具有相似性的Stack Overflow问题是this,但与我的问题无关。

    修改 以下代码在启动时在我的WinForms测试应用程序中执行:

    SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder();
    
    connectionStringBuilder.DataSource = m_DataSource;
    connectionStringBuilder.InitialCatalog = m_InitialCatalog;
    connectionStringBuilder.UserID = m_UserID;
    connectionStringBuilder.Password = m_Password;
    connectionStringBuilder.IntegratedSecurity = false;
    connectionString = connectionStringBuilder.ConnectionString;
    
    m_DatabaseConnection = new SqlConnection(connectionString);
    

    然后我有2个按钮;其中一个调用上面提到的 SPROC 1 ,另一个调用不同的SPROC,它没有相同的减速问题。单击任一按钮时执行以下代码(仅差异为SPROC名称):

    m_DatabaseConnection.Open();
    m_DatabaseCommand = new SqlCommand("GetCompanies", m_DatabaseConnection);
    m_DatabaseCommand.Parameters.AddWithValue("@StatusID", StatusID);
    m_DatabaseCommand.CommandType = CommandType.StoredProcedure;
    m_DatabaseCommand.CommandTimeout = 0;
    
    SqlDataAdapter databaseDataAdapter = new SqlDataAdapter(m_DatabaseCommand);
    DataSet databaseDataSet = new DataSet();
    databaseDataAdapter.Fill(databaseDataSet);
    m_DatabaseConnection.Close();
    

1 个答案:

答案 0 :(得分:3)

以下是调试此问题的想法:

  • 在处置连接后尝试调用SqlConnection.ClearAllPools()。如果这可以解决问题,那么问题肯定与特定连接有关。
  • 接下来,将SPROC包含在显式事务中。
  • 接下来,在调用SPROC之前调用SqlConnection.ClearAllPools()。
  • SPROC返回了多少数据?
  • 请发布您用来打开连接的C#代码并执行SPROC。
  • 创建一个独立的控制台应用程序,可以重现您所看到的行为。这将(可能)证明您的应用程序中存在某些问题,因为控制台应用程序运行正常。