7

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

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

这只发生在少数存储过程中。一个是SELECT带有 2 的简单查询JOINs,(SPROC 1)另一个是 1600+ 行 SPROC (SPROC 2)。

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

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

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

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

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

花了好几天的时间来缩小最初在更大的应用程序中观察到的问题,以便创建一个测试应用程序来轻松测试/重现它。

从我在这里阅读的内容来看,有 4 到 8 分钟的超时(SqlConnection.Close()在代码中调用之后),此时它会关闭与数据源的数据库连接。这似乎符合我上面提到的场景 2。

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

我们正在使用 .Net 2.0 框架,如果这有什么不同的话。

上面列出了很多细节,所以如果我需要澄清任何事情,请告诉我。

唯一有任何相似之处的 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();
4

1 回答 1

3

这是我调试此问题的想法:

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