Есть несколько сценариев, в которых курсоры на самом деле работают лучше, чем основанные на множестве эквиваленты. Постоянные итоги - это то, что всегда приходит на ум - поищите слова Ицик по этому поводу (и не обращайте внимания на любые слова, связанные с SQL Server 2012, который добавляет новые функции управления окнами, которые дают курсорам возможность заработать деньги в этой ситуации).
Одна из больших проблем, с которыми люди сталкиваются с курсорами, заключается в том, что они работают медленно, они используют временное хранилище и т. Д. Это отчасти потому, что синтаксис по умолчанию - это глобальный курсор со всеми видами неэффективных параметров по умолчанию. В следующий раз, когда вы делаете что-то с курсором, который не должен делать что-то вроде UPDATE...WHERE CURRENT OF
(что я смог избежать всей своей карьеры), сравните эти два варианта синтаксиса:
DECLARE c CURSOR
FOR <SELECT QUERY>;
DECLARE c CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR <SELECT QUERY>;
Фактически, первая версия представляет ошибку в недокументированной хранимой процедуре sp_MSforeachdb, которая заставляет ее пропускать базы данных, если состояние какой-либо базы данных изменяется во время выполнения. Впоследствии я написал свою собственную версию хранимой процедуры (см. здесь и здесь ), которая исправила ошибку (просто используя последнюю версию синтаксиса выше) и добавила несколько параметров в контролировать, какие базы данных будут выбраны.
Многие люди думают, что методология не является курсором, потому что она не говорит DECLARE CURSOR
. Я видел, как люди утверждают, что цикл while быстрее курсора (, который, я надеюсь, я здесь развеял ) или что использование FOR XML PATH
для выполнения групповой конкатенации не выполняет скрытую операцию курсора. Глядя на план во многих случаях покажет правду.
Во многих случаях используются курсоры, когда набор на основе более подходит. Но существует множество допустимых вариантов использования, когда на основе набора гораздо сложнее написать эквивалент, для оптимизатора сгенерировать план для обоих или невозможно (например, задачи обслуживания, когда вы просматриваете таблицы для обновления статистики, вызов хранимой процедуры для каждого значения в результате и т. д.). То же самое верно для многих больших многостоловых запросов, когда план становится слишком чудовищным для оптимизатора. В этих случаях может быть лучше сначала поместить некоторые промежуточные результаты во временную структуру. То же самое касается некоторых основанных на множествах эквивалентов курсорам (например, промежуточные итоги). Я также писал о другом способе, когда люди почти всегда инстинктивно думают об использовании цикла и курсора while, и существуют умные альтернативы на основе множеств, которые намного лучше .
ОБНОВЛЕНИЕ 2013-07-25
Просто хотел добавить несколько постов в блоге, которые я написал о курсорах, какие опции вы должны использовать, если вам нужно делать , и использовать запросы на основе множеств вместо циклов для генерации множеств :
Лучшие подходы для подведения итогов - обновлено для SQL Server 2012
Какое влияние могут оказать различные параметры курсора?
Создание набора или последовательности без циклов: [Часть 1] [Часть 2] [Часть 3]