5

在发布这个问题之前,我已经阅读了这个网站上的几个答案:like thisthis。每个人似乎都同意“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.5576016 - 00:00:00.1110324 appr 0.44)比实际工作(第二个基准测试中的 00:00:00.1110324)多四倍。我错过了什么?

编辑:我针对在 RAM 磁盘上创建的数据库运行这些基准测试,因此我所有的数据库操作都非常快。

4

2 回答 2

4

你的基准对我来说很有意义。如果您在没有连接池的情况下为每次迭代打开和关闭连接,情况会更糟,但这是一个完全不同的故事。但是,当您关闭一个池连接时,您会将其返回到池中:在幕后,SNAC 发出 sp_reset_connection 并将连接放回池中。通常,这是一个非常快的操作(除非发生阻塞),但它必须花费一些小但非零的时间。
重复使用相同的连接而不关闭和打开每次迭代,避免了这种小的滞后。
但是,如果您比较池连接和非池连接的相同用途,对我来说会更有意义。你试过吗?

这是关于 sp_reset_connection 的有趣帖子

于 2013-01-09T17:05:36.393 回答
1

+1 to @spaghettidba - I agree, and to add some comments.....

My approach in the past has been to use the same connection multiple times - save having to even go to the connection pool to get a connection each time which I've always assumed (not measured) has some cost as @spaghettidba said.

The main performance benefit of the pool, is the scenario where it doesn't make sense/can't reuse the same connection instance - in which case getting a previously used connection from the pool is much faster as it doesn't actually need to go off and actually try to connect to the server, it just assumes it's there and available - i.e. connection.Open() in my experience doesn't error for a pooled connection even if the server is down - it will just error when you try to execute anything against the connection.

于 2013-01-09T17:24:55.640 回答