ADO.Net:重复打开SqlConnection或每次都换一个新的?

时间:2013-01-09 15:31:20

标签: sql-server-2008 c#-4.0 ado.net sql-server-2008-r2

在发布此问题之前,我已在此网站上阅读了几个答案: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.1110324)多四倍的时间(00:00:00.5576016 - 00:00:00.1110324 appr 0.44)。我错过了什么?

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

2 个答案:

答案 0 :(得分:4)

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

这是interesting post on sp_reset_connection

答案 1 :(得分:1)

+1来@spaghettidba - 我同意,并添加一些评论......

我过去的方法是多次使用相同的连接 - 除了每次我总是假设(未测量)一些之外,甚至连接到连接池以获得连接em>费用为@spaghettidba说。

池的主要性能优势是,它没有意义/无法重用相同的连接实例 - 在这种情况下,从池中获取以前使用的连接要快得多,因为它没有实际上需要关闭并实际尝试连接到服务器,它只是假设它在那里并且可用 - 即我的经验中的connection.Open()即使服务器关闭也没有错误的池化连接 - 它只会出错当你尝试对连接执行任何操作时。