如SQL Profiler中所见,对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倍。
我检查过profiler是专门报告的毫秒数。
我没有使用SqlCommand.ExecuteReader的异步版本。
Profiler持续时间不是我使用Profiler开始和结束时间读取和验证的多个线程/核心的所有时间总和。
赞赏的想法。
答案 0 :(得分:2)
因为您只有批次的开始时间。如果你消费数据,那么时间可能会排成一行:
using(var dr = comm.ExecuteReader()) {
do {
while(dr.Read()) {}
} while (dr.NextResult());
}
顺便提一下,还有一些SET
选项可以改变某些查询的性能 - 不确定应该在这里应用,但它会显着影响具有计算+持久值的表:如果{{1创建列时,值与设置不兼容,需要重新运行每行的计算。对于计算的+持久+索引列,如果要对该列进行过滤,则尤其值得注意 - 它必须执行表扫描(或类似)而不是索引扫描/索引搜索。