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

njb*_*njb 7 .net c# sql-server performance connection-pooling

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

  1. 如果a SqlConnection在所有测试期间打开并保持打开状态,则SPROC会逐渐变慢,直到运行任何其他 SPROC 或查询.
  2. 如果a SqlConnection在每次执行时打开和关闭,SPROC会逐渐变慢,直到至少8分钟过去.

只有少数存储过程才会发生这种情况.一个是SELECT2 的简单查询JOINs,(SPROC 1)另一个是大规模1600+线SPROC(SPROC 2).

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

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

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

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

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

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

从我在这里读到的,有一个4到8分钟的超时(SqlConnection.Close()在代码中调用之后),此时它关闭了与数据源的数据库连接.这似乎与我上面提到的方案2一致.

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

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

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

唯一存在任何相似之处的Stack Overflow问题是这个,但与我的问题无关.

编辑: 以下代码在启动时在我的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);
Run Code Online (Sandbox Code Playgroud)

然后我有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();
Run Code Online (Sandbox Code Playgroud)

usr*_*usr 3

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

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