【发布时间】:2012-04-11 20:15:04
【问题描述】:
从 C# .Net 应用程序通过网络运行相同存储过程会随着每次后续执行而逐渐变慢。它似乎花费了上一次执行的 两倍 时间(达到最大值;请继续阅读)。执行时间逐渐变慢,直到发生 2 个场景中的一个,此时 SPROC 的第一次执行再次“快速”。
- 如果
SqlConnection在所有测试期间打开并保持打开状态, 在运行 任何其他 SPROC 或查询之前,SPROC 会逐渐变慢。 - 如果在每次执行前后打开和关闭
SqlConnection,则 SPROC 会逐渐变慢,直到 至少 8 分钟过去。
这只发生在少数存储过程中。一个是带有 2 个 JOINs 的简单 SELECT 查询,(SPROC 1) 另一个是 1600+ 行的大型 SPROC (SPROC 2)。
SPROC 1 的执行时间似乎永远不会超过 60 秒,SPROC 2 的执行时间永远不会超过 67 秒。 SPROC 1 初始执行时间不到一秒,SPROC 2 初始执行时间为 7 秒。
仅当 SPROC 在应用程序中使用相同的 SqlConnection 运行时才会发生这种情况。一旦使用了 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 框架,如果这有什么不同的话。
上面列出了很多细节,所以如果我需要澄清任何事情,请告诉我。
唯一有任何相似之处的 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();
【问题讨论】:
-
这可能是在dba 上发布的更好的内容。
-
这一定是因为你的代码。但是,由于您没有向我们展示您的代码,我们无法为您提供帮助。
-
@JohnSaunders - 如果需要,我可以发布对 SPROC 1 的查询,但我认为没有人会从 1600+ 行 SPROC 2 中受益。
-
你能在 pastebin 上上传 SPROC2 吗?这样我们至少可以滚动查看可疑模式。
标签: c# .net sql-server performance connection-pooling