13

私のプロファイラ トレースは、exec sp_reset_connectionすべての SQL バッチまたはプロシージャ コールの間に呼び出されていることを示しています。それには理由がありますが、パフォーマンスを向上させるために不要であると確信している場合、呼び出されないようにすることはできますか?

更新: これによりパフォーマンスが向上すると考える理由は 2 つあります。

  1. SQL Server は接続状態をリセットする必要はありません。これは比較的無視できる改善だと思います。
  2. exec sp_reset_connectionクライアントが を送信し、応答を待ってから、実際に実行したい SQLを送信する必要がないため、ネットワーク レイテンシが短縮されます。

2 番目の利点は、私が興味を持っているものです。私のアーキテクチャでは、クライアントがデータベースから離れていることがあるためです。すべての SQL バッチまたは rpc で 2 回のラウンドトリップが必要な場合、ネットワーク遅延の影響が 2 倍になります。このような二重呼び出しをなくすと、パフォーマンスが向上する可能性があります。

はい、アプリの再構築など、パフォーマンスを改善するためにできることは他にもたくさんあります。私は問題の根本原因を解決することが大好きですが、この場合、sp_reset_connection を防ぐことができるかどうかを知りたいだけです。呼ばれること。次に、パフォーマンスの向上があるかどうかをテストし、これを呼び出さない場合のリスクを適切に評価できます。

これにより、別の質問が生じます。sp_reset_connection を使用したネットワーク通信は、上で概説したように本当に発生するのでしょうか? つまり、クライアントは を送信exec sp_reset_connectionし、応答を待ってから、実際の SQL を送信しますか? それとも、すべて 1 つのチャンクにまとめますか?

4

4 に答える 4

9

.NET を使用して SQL Server に接続している場合、追加のリセット呼び出しの無効化は .NET 3.5 の時点で無効になっています。こちらを参照してください。(プロパティは残りますが、何もしません。)

Microsoft は (誰かがここで実験的に行ったように)、リセットを回避するためにドアを開くことは、(おそらく) わずかなパフォーマンスの向上を得るよりもはるかに危険であることに気付いたと思います。彼らのせいだとは言えません。


クライアントは を送信exec sp_reset_connectionし、応答を待ってから、実際の SQL を送信しますか?

編集:私は間違っていました --ここを参照してください-- 答えはノーです。

概要: TDS メッセージには、接続をリセットする必要があることを指定する特別なビット セットがあり、SQL Server がsp_reset_connection自動的に実行されます。プロファイラーでは別のバッチとして表示され、実行したい実際のクエリの前に常に実行されるため、私のテストは無効でした。

はい、別のバッチで送信されます。

興味があったので、これを実証するために小さな C# テスト プログラムを作成しました。

using System.Data.SqlClient;

(...)

private void Form1_Load(object sender, EventArgs e)
{
    SqlConnectionStringBuilder csb = new SqlConnectionStringBuilder();
    csb.DataSource = @"MyInstanceName";
    csb.IntegratedSecurity = true;
    csb.InitialCatalog = "master";
    csb.ApplicationName = "blarg";

    for (int i = 0; i < 2; i++)
        _RunQuery(csb);
}

private void _RunQuery(SqlConnectionStringBuilder csb)
{
    using (SqlConnection conn = new SqlConnection(csb.ToString()))
    {
        conn.Open();

        SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:00:05'", conn);

        cmd.ExecuteNonQuery();
    }
}

Profiler を起動し、選択したインスタンスにアタッチして、提供したダミーのアプリケーション名でフィルタリングします。次に、cmd.ExecuteNonQuery();行にブレークポイントを置き、プログラムを実行します。

最初にステップ オーバーすると、クエリだけが実行され、5 秒間待機した後に取得されるのは SQL:BatchCompleted イベントだけです。ブレークポイントが 2 回目に到達すると、プロファイラーに表示されるのは 1 つのイベントだけです。もう一度ステップ オーバーすると、すぐにイベントexec sp_reset_connectionが表示され、遅れて SQL:BatchCompleted イベントが表示されます。

呼び出しを取り除く唯一の方法exec sp_reset_connection(これは、正当なパフォーマンスの問題である場合とそうでない場合があります) は、.NET の接続プールをオフにすることです。そして、それを計画している場合は、おそらく独自の接続プーリングメカニズムを構築したいと思うでしょう。なぜなら、それをオフにして他に何もしないことは、おそらく余分なラウンドトリップの打撃を受けるよりも全体的に悪影響を与えるからです。正確性の問題を手動で処理します。

于 2012-04-27T17:13:34.820 に答える
3

次の Q/A が役立ちます: Sql Server Profiler で "exec sp_reset_connection" とはどういう意味ですか?

ただし、Entity Framework と MS-SQL 2008 R2 を使用して簡単なテストを行いました。最初の呼び出しの後、「exec sp_reset_connection」に時間がかからないことがわかります。

for (int i = 0; i < n; i++)
{
    using (ObjectContext context = new myEF())
    {
                
        DateTime timeStartOpenConnection = DateTime.Now;
        context.Connection.Open();
        Console.WriteLine();
        Console.WriteLine("Opening connection time waste: {0} ticks.", (DateTime.Now - timeStartOpenConnection).Ticks);

        ObjectSet<myEntity> query = context.CreateObjectSet<myEntity>();
        DateTime timeStart = DateTime.Now;
        myEntity e = query.OrderByDescending(x => x.EventDate).Skip(i).Take(1).SingleOrDefault<myEntity>();
        Console.Write("{0}. Created By {1} on {2}... ", e.ID, e.CreatedBy, e.EventDate);
        Console.WriteLine("({0} ticks).", (DateTime.Now - timeStart).Ticks);

        DateTime timeStartCloseConnection = DateTime.Now;
        context.Connection.Close();
        context.Connection.Dispose();
        Console.WriteLine("Closing connection time waste: {0} ticks.", (DateTime.Now - timeStartCloseConnection).Ticks);
        Console.WriteLine();
    }
}

出力は次のとおりです。

接続を開く時間の無駄: 5390101ティック。585. 2011/12/20 2:18:23 PM に sa によって作成されました... (2560183 ティック)。接続時間の無駄を閉じる: 0 ティック。

接続を開く時間の無駄: 0 ティック。584. 2011/12/20 2:18:20 PM に sa によって作成されました... (1730173 ティック)。接続時間の無駄を閉じる: 0 ティック。

接続を開く時間の無駄: 0 ティック。583. 2011/12/20 2:18:17 PM に sa によって作成されました... (710071 ティック)。接続時間の無駄を閉じる: 0 ティック。

接続を開く時間の無駄: 0 ティック。582. 2011/12/20 2:18:14 PM に sa によって作成されました... (720072 ティック)。接続時間の無駄を閉じる: 0 ティック。

接続を開く時間の無駄: 0 ティック。581. 2011/12/20 2:18:09 PM に sa によって作成されました... (740074 ティック)。接続時間の無駄を閉じる: 0 ティック。

したがって、最終的な結論は次のとおりです。「exec sp_reset_connection」について心配する必要はありません。それは何も無駄にしません。

于 2012-03-08T19:37:04.700 に答える
2

個人的には残しておきます。

それが何をするかを考えると、スコープ内に一時テーブルがないこと、またはトランザクションが開いたままになっていないことを確認したいと思います。

公平を期すために、本番データベースに対してプロファイラーを実行しないことで、パフォーマンスが大幅に向上します。そして、これから何を得ることができるかについて、数値、記事、または推奨事項はありますか?

于 2010-10-30T13:12:14.863 に答える
0

接続をプールに戻すのではなく、開いたままにし、その 1 つの接続ですべてのコマンドを実行します。

于 2010-10-23T13:52:47.677 に答える