5

この質問を投稿する前に、私はこのサイトでいくつかの回答を読みました:これこれのように。「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();
    }

どうやら、プールからの接続の取得には、実際の作業(2番目のベンチマークの00:00:00.1110324)の4倍の時間がかかります(00:00:00.5576016-00:00:00.1110324 appr 0.44)。私は何が欠けていますか?

編集:RAMディスク上に作成されたデータベースに対してこれらのベンチマークを実行しているため、すべてのデータベース操作が非常に高速です。

4

2 に答える 2

4

あなたのベンチマークは私には理にかなっています。接続プールを使用せずに反復ごとに接続を開いたり閉じたりするとさらに悪いことになりますが、それはまったく別の話です。ただし、プールされた接続を閉じると、代わりにプールに返されます。裏で、SNAC は sp_reset_connection を発行し、接続をプールに戻します。通常、これは非常に高速な操作ですが (ブロックが開始されない限り)、わずかではあるがゼロではない時間が必要です。
反復ごとに閉じたり開いたりせずに同じ接続を再利用すると、この小さな遅延が回避されます。
ただし、プールされた接続とプールされていない接続の同じ使用法を比較すると、より理にかなっています。あなたはそれを試しましたか?

これは sp_reset_connection に関する興味深い投稿です

于 2013-01-09T17:05:36.393 に答える
1

+1 @spaghettidba - 同意します。コメントを追加します.....

過去の私のアプローチは、同じ接続を複数回使用することでした- @spaghettidbaが言ったように、私が常に想定していた(測定されてない)毎回接続を取得するために接続プールに行く必要さえありません。

プールの主なパフォーマンス上の利点は、それが意味をなさない/同じ接続インスタンスを再利用できないシナリオです。オフになって実際にサーバーに接続しようとすると、サーバーが存在して利用可能であると想定されます-つまり、私の経験では、サーバーがダウンしていても、プールされた接続に対してconnection.Open()はエラーになりません-試してみるとエラーになります接続に対して何かを実行します。

于 2013-01-09T17:24:55.640 に答える