2

SQL プロファイラーで見られるように、SqlCommand.ExecuteReader への呼び出しは、SQL バッチ自体よりも完了するのに時間がかかるのはなぜですか?

SqlCommand.ExecuteReader を呼び出すコンソール アプリで次の単純なコードを実行しています。これには、Stopwatch オブジェクトを使用しています。

var swQueryTime = new Stopwatch();

        var conn = new SqlConnection("Data Source=.;Initial Catalog=master;Trusted_Connection=True;");
        conn.Open();
        string sql = string.Format(@"select * from sys.dm_os_memory_clerks; select * from sys.dm_os_performance_counters ");

        for (int i = 0; i < 10; i++)
        {                
            var comm = new SqlCommand(sql, conn);
            swQueryTime.Restart();

            var dr = comm.ExecuteReader();

            swQueryTime.Stop();

            Console.WriteLine("ElapsedMilliseconds: {0}", swQueryTime.ElapsedMilliseconds);

            dr.Close();
            comm = null;
        }

平均して、SQL バッチの所要時間は、.Net 側で報告される時間の 4 倍です。

プロファイラーが具体的にミリ秒を報告していることを確認しました。

私は SqlCommand.ExecuteReader の非同期バージョンを使用していません。

プロファイラーの期間は、プロファイラーの開始時間と終了時間を使用して読んで検証したものから、複数のスレッド/コアにわたるすべての時間の合計ではありません。

アイデアを歓迎します。

4

1 に答える 1

2

バッチの開始までのタイミングしか得られないためです。データも消費する場合、時間はおそらく一致します。

using(var dr = comm.ExecuteReader()) {
    do {
        while(dr.Read()) {}
    } while (dr.NextResult());
}

ちなみに、SET一部のクエリのパフォーマンスを変更できるいくつかのオプションもあります-ここで適用する必要があるかどうかはわかりませんが、計算された値と永続化された値を持つテーブルに大きな影響を与える可能性があります:SET列が設定されているときに値が設定と互換性がない場合行ごとに計算を再実行する必要があります。これは、その列をフィルタリングしている場合、計算された + 永続化された + インデックス付きの列で特に顕著です。インデックススキャン/インデックスシークではなく、テーブルスキャン (または同様の) を実行する必要があります。

于 2013-03-06T13:18:11.177 に答える