2013-03-06 1 views
2

Как вызов SqlCommand.ExecuteReader занимает меньше времени, чем сам пакет SQL, как видно из SQL Profiler?SqlCommand.ExecuteReader длительность меньше, чем SQL Продолжительность пакета профилирования

У меня есть следующий простой код работает в консольном приложении, которое вызывает SqlCommand.ExecuteReader, которые я время с помощью секундомера объекта:

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 партии в 4 раза больше, чем сообщаются на стороне .Net.

Я проверил профайлер, который конкретно сообщает миллисекунды.

Я не использую асинхронную версию SqlCommand.ExecuteReader.

Продолжительность профайлера - это не сумма всех времен от нескольких потоков/ядер от того, что я прочитал и проверил, используя время начала и окончания профайлера.

Идеи оценены.

+0

+1: для проверки Sql Profiler Milli/Micro-second thing. – RBarryYoung

+0

Вы проверили продолжительность самого заявления Sql в Profiler? Это всегда несколько меньше, чем Batch Duration, обычно разница небольшая, но иногда это значимо. – RBarryYoung

+0

Да, я проверил продолжительность инструкции - сумма двух операторов суммируется с ожидаемой продолжительностью партии. – user2139987

ответ

2

Потому что у вас есть только тайминги до самого начала партии. Если вы потребляете данных тоже, время, вероятно выстраиваться:

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

Кстати, есть также несколько SET вариантов, которые могут изменить производительность некоторых запросов - не уверены, что следует применять здесь, но может значительно повлиять на таблицы, которые рассчитали + сохраненные значения: если значения SET несовместимы с настройками, когда был создан столбец, ему нужно будет повторно запустить вычисление для каждой строки. Это особенно заметен для вычисленных + сохраненных + индексированных столбцов, если вы фильтруете этот столбец - ему придется выполнять сканирование таблицы (или подобное), а не поиск индекса/индекса.

+0

+1: Вероятно, это так. – RBarryYoung

+0

Да, это делает профилировщик, и ExecuteReader соглашается на тайминги - спасибо! Мое чтение в ExecuteReader заставило меня поверить, что он ждал, пока все данные будут возвращены, прежде чем перейти к следующему утверждению. Знаете ли вы, что это альтернативное поведение документировано где угодно? – user2139987

+0

@ user2139987 Я не проверял, но в принципе он возвращает TDS, который является потоком - вы можете начать читать данные задолго до того, как дойдете до конца потока. Конечно, это явно имеет место при использовании режима 'SequentialAccess', поскольку он даже считывает отдельные столбцы в виде потока. Вы также можете увидеть побочные эффекты этого потокового поведения, если вы попытаетесь получить доступ к параметрам 'out'/'ref' до конца данных - они возвращаются * last *. Вы также можете делать такие вещи, как повышение sql-ошибки после длительного выбора - если вы закроете читателя до конца, вы никогда не увидите ошибку. –

Смежные вопросы