在发布此问题之前,我已在此网站上阅读了几个答案:like this和this。每个人似乎都同意“c#应用程序池针对同一数据库的多次调用进行了优化。”
但是,如果我从池中获得连接,我仍然会观察到相当大的性能损失。这是我的基准:
private const string localConnString = "Data Source=(local);Integrated Security=SSPI;database=MyTest;Pooling=true";
[Test]
public void GetNewConnectionEveryTime()
{
var stopwatch = new Stopwatch();
stopwatch.Start();
for (var i = 0; i < 1000; i++)
{
using (var conn = new SqlConnection(localConnString))
{
conn.Open();
const string saveTrancount = "EXEC dbo.TestTran";
ExecuteSql(conn, saveTrancount);
}
}
stopwatch.Stop();
Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
//Time elapsed: 00:00:00.5576016
}
[Test]
public void ReuseOneConnection()
{
var stopwatch = new Stopwatch();
stopwatch.Start();
using (var conn = new SqlConnection(localConnString))
{
conn.Open();
for (var i = 0; i < 1000; i++)
{
const string saveTrancount = "EXEC dbo.TestTran";
ExecuteSql(conn, saveTrancount);
}
}
stopwatch.Stop();
Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
//Time elapsed: 00:00:00.1110324
}
private void ExecuteSql(SqlConnection conn, string sql, int timeout = 0)
{
var command = conn.CreateCommand();
command.CommandText = sql;
command.CommandType = CommandType.Text;
command.CommandTimeout = timeout;
command.ExecuteNonQuery();
}
显然从池中获取连接需要比实际工作(第二个基准测试中的00:00:00.1110324)多四倍的时间(00:00:00.5576016 - 00:00:00.1110324 appr 0.44)。我错过了什么?
编辑:我正在针对在RAM磁盘上创建的数据库运行这些基准测试,因此我的所有数据库操作都非常快。
答案 0 :(得分:4)
你的基准对我有意义。如果你在没有连接池的情况下打开和关闭每次迭代的连接会更糟糕,但这是一个完全不同的故事。
但是,当您关闭池连接时,而是将其返回到池中:在封面下,SNAC发出sp_reset_connection并将连接放回池中。
通常,这是一个非常快速的操作(除非阻止踢),但它必须采取一些小但非零的时间。
重复使用相同的连接而不关闭和打开每次迭代,避免这种小的滞后。
但是,如果你比较混合和非合并连接的相同的使用,那对我来说会更有意义。你试过了吗?
答案 1 :(得分:1)
+1来@spaghettidba - 我同意,并添加一些评论......
我过去的方法是多次使用相同的连接 - 除了每次我总是假设(未测量)一些>之外,甚至连接到连接池以获得连接em>费用为@spaghettidba说。
池的主要性能优势是,它没有意义/无法重用相同的连接实例 - 在这种情况下,从池中获取以前使用的连接要快得多,因为它没有实际上需要关闭并实际尝试连接到服务器,它只是假设它在那里并且可用 - 即我的经验中的connection.Open()即使服务器关闭也没有错误的池化连接 - 它只会出错当你尝试对连接执行任何操作时。