SqlCommand.Cancel () вызывает повышение производительности? - PullRequest
10 голосов
/ 17 августа 2010

Я видел, как это показывает несколько мест в коде, никогда без объяснения, просто загадочный комментарий над ним (объявление и выполнение включены для представления контекста. Это просто стандартная процедура запуска SqlCommand):

//SqlCommand cmd = new SqlCommand();
//cmd.ExecuteReader();
//Read off the results

//Cancel the command. This improves query time.
cmd.Cancel ();

По сути, после завершения запроса он возвращается и отменяет его, требуя некоторого повышения производительности.Я полагаю, вы можете вернуть некоторую память, когда она выйдет и освободит XmlReader, но обычно она все равно выйдет из области видимости.

Я никогда не беспокоился об этом раньше, но, в конце концов, в некоторыхКод, который я рассматриваю. Ускоряет ли отмена SqlCommand после запуска его в коде на самом деле, или это просто какое-то странное суеверие программиста?

Ответы [ 4 ]

14 голосов
/ 17 августа 2010

Согласно MSDN , это правильно.

Метод Close заполняет значения для выходных параметров, возвращаемых значений и RecordsActed, увеличивая время, необходимое для закрытия SqlDataReader, который использовался для обработки большого или сложного запроса.Если возвращаемые значения и количество записей, затронутых запросом, не являются значительными, время, необходимое для закрытия SqlDataReader, можно уменьшить, вызвав метод Cancel связанного объекта SqlCommand перед вызовом метода Close.

Странно!

8 голосов
/ 20 июня 2013

Вызов Cancel дает потенциально МАССИВНОЕ улучшение производительности , если ваш вызов ExecuteReader возвращает большое количество строк, и вы не читаете все строки .

Для иллюстрации, скажем, запрос возвращает миллион строк, и вы закрываете читатель после прочтения только первых 1000 строк.Если вам не удастся вызвать Cancel перед закрытием считывателя, метод Close заблокирует , пока он внутренне перечислит все оставшиеся 999 000 строк

Попробуйте и посмотрите!

0 голосов
/ 14 августа 2014

В вашем примере вы открываете считыватель, читаете все строки и команду «Отмена», но не показываете, где читатель закрывался.

Убедитесь, что отмена происходит до Dispose / Close. Например, вы не получите повышение производительности в этом примере (к сожалению, реальный код в производстве):

using (var rdr = cmd.ExecuteReader (CommandBehavior.Default))
{
   retval = DocumentDir.DBRead (rdr);
}

// Optimization.  Allows reader to close more quickly.... NOT!
cmd.Cancel ();  // bad!

Жаль, что оно уже закрыто оператором Using!

Вот как следует читать, чтобы понять потенциальную выгоду:

using (var rdr = cmd.ExecuteReader (CommandBehavior.Default))
{
   retval = DocumentDir.DBRead (rdr);

   // Optimization.  Allows reader to close more quickly.
   cmd.Cancel ();
}

С MSDN SqlCommand.Cancel :

В некоторых, редких случаях, если вы вызываете ExecuteReader, затем вызываете Close (неявно или явно) перед вызовом Cancel, а затем вызываете Cancel, команда отмены не отправляется на SQL Server, и набор результатов может продолжаться для потоковой передачи после вызова Close. Чтобы избежать этого, обязательно вызовите Cancel перед закрытием считывателя или соединения.

0 голосов
/ 13 сентября 2012

Наша техническая команда в Cinchcast провела некоторое тестирование, и мы обнаружили, что добавление cmd.Cancel () на самом деле замедляет его.

У нас есть вызов DALC, который получает список эпизодов для хоста.Мы запустили его 1000 раз и получили среднее время отклика для возврата 10 эпизодов.

Итак, с возвращением 10 шоу Среднее с отменой: 0,069 с Среднее без отмены: 0,026 с

Довольно значительно медленнее при запускес возвращением 10 эпизода.

Итак, я снова попытался с возвратом 100 эпизодов, чтобы увидеть, имеет ли значение больший набор результатов.

То есть с возвратом 100 шоу при каждом вызове Среднее с отменой: 0,132 с Среднее без отмены:0,122 с

Так что на этот раз разница во времени была намного меньше.Это все еще быстрее, хотя без использования Отмена для наших обычных случаев использования.

...