Когда курсоры TSQL являются лучшим или единственным вариантом? - PullRequest
4 голосов
/ 29 июля 2011

У меня есть аргумент об использовании курсоров в TSQL недавно ...

Прежде всего, я не болельщик в дебатах. Но каждый раз, когда кто-то говорит курсор , всегда есть какой-нибудь тупик (или 50), который набрасывается с обязательными «курсорами - злые» мантры. Я знаю, что SQL-сервер был оптимизирован для операций, основанных на множествах, и, возможно, курсоры действительно являются воплощением зла, но если бы я хотел обдумать это объективно ...

Вот куда движется мой разум:

1) Единственное различие между курсорами и операциями над множествами заключается в производительности ?

Редактировать : Был хороший аргумент в пользу того, что это не просто вопрос производительности - например, многократный запуск одного пакета для списка идентификаторов или, альтернативно, выполнение фактического Текст SQL хранится в поле таблицы строка за строкой.

2) Последующие действия: курсоры всегда работают хуже?

EDIT : @Martin показывает хороший случай, когда курсоры значительно превосходят операции на основе множеств. Я подозреваю, что это было бы не то, что вы бы делали слишком часто (до того, как вы прибегли к какому-то решению OLAP / Data Warehouse), но, тем не менее, похоже, что вы действительно не может жить без курсора.

- ссылка на эталонные тесты TPC с указанием курсоров может быть более конкурентоспособным, чем обычно считают люди.
- ссылка на оптимизации использования памяти для курсоров начиная с Sql-Server 2005

3) Есть ли проблемы, о которых вы можете подумать, что курсоры лучше подходят для решения, чем операции на основе множеств?

РЕДАКТИРОВАТЬ : Операции на основе набора буквально не могут Execute хранимые процедуры и т. Д. (См. Выше, см. Пункт 1).
EDIT : Операции на основе множеств экспоненциально медленнее, чем строка за строкой, когда дело доходит до агрегирования больших наборов данных.

  • Статья из MSDN , объясняющая их точку зрения из наиболее распространенных проблем, с которыми люди прибегают к курсорам объяснение методов, основанных на множествах, которые будут работать лучше.
  • Microsoft (смутно) говорит в 2008 Transact SQL Reference на MSDN : «... бывают случаи, когда результаты лучше всего обрабатывать по одной строке за раз», но ничего не дают примеры того, на какие случаи они ссылаются.

Главным образом, я собираюсь преобразовать курсоры в операции на основе множеств в моем старом коде, если / когда я делаю какие-либо существенные обновления для различных приложений, если есть что-то из этого. (Я склонен к лени из-за чистоты в большинстве случаев - то есть, если она не сломана, не чинить ее.)

Ответы [ 4 ]

4 голосов
/ 29 июля 2011

Чтобы ответить на ваш вопрос напрямую:

Мне еще не приходилось сталкиваться с ситуацией, когда операции над множествами не могли бы делать то, что в противном случае могло бы быть сделано с помощью курсоров.Тем не менее, существуют ситуации, когда использование курсоров для разбиения большой задачи на более управляемые куски является лучшим решением для обеспечения поддержки кода, ведения журналов, управления транзакциями и тому подобного.Но я сомневаюсь, что есть какие-то жесткие правила, чтобы сказать вам, какие типы требований приведут к тому или иному решению - отдельные базы данных и потребности просто слишком разные.

Тем не менее, я полностьюсогласиться с вашим подходом «если не сломано, не исправляйте».Рефакторинг процедурного кода для установки операций для процедуры, которая работает просто отлично, мало что дает.Тем не менее, хорошее эмпирическое правило - сначала искать решение, основанное на множествах, и заходить в процедурный код только тогда, когда это необходимо.Кишка чувствовать?Если вы используете курсоры более 20% времени, вы делаете что-то не так.

И то, что я действительно хочу сказать:

Когда яИнтервью с программистами. Я всегда задаю им пару довольно сложных вопросов SQL и прошу их объяснить, как они их решат.Это проблемы, которые, как я знаю, могут быть решены с помощью операций над множествами, и я специально ищу кандидатов, которые могут решить их без процедурных подходов (то есть курсоров).

Это , а не потому что я считаю, что в любом подходе есть что-то хорошее или более эффективное - разные ситуации дают разные результаты.Скорее потому, что, по моему опыту, программисты либо получают концепцию операций на основе множеств, либо нет.Если этого не произойдет, они потратят слишком много времени на разработку комплексных процедурных решений для проблем, которые можно решить гораздо быстрее и проще с помощью операций на основе множеств.

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

3 голосов
/ 30 июля 2011

Промежуточные итоги - классический случай, когда по мере увеличения количества строк курсоры могут не выполнять операции на основе набора, поскольку, несмотря на более высокую фиксированную стоимость курсора, требуемая работа растет линейно, а не экспоненциально, как при «треугольном соединении» на основе набора. подход.

Ицик Бен Ган проводит здесь некоторые сравнения .

Graph

Denali имеет более полную поддержку для предложения OVER, однако это должно сделать это использование избыточным.

2 голосов
/ 29 июля 2011

Часто, когда вы строите динамический SQL, вы должны использовать курсоры. Представьте себе скрипт, который ищет во всех таблицах в базе данных одно и то же значение в разных полях. Лучшим решением будет курсор. Вопрос, где проблема возникла, здесь Как использовать EXEC или sp_executeSQL без циклов в этом случае? Я буду очень впечатлен, если кто-нибудь сможет решить эту проблему лучше без курсора.

2 голосов
/ 29 июля 2011

Поскольку я видел, что людям удается заново реализовать курсоры (во всех их различных формах), используя другие конструкции TSQL (обычно включающие хотя бы один цикл while), нет ничего, что курсоры могли бы достичь, чего не может не должно быть сделано с использованием других конструкций.

Это не означает, что повторные реализации не столь же неэффективны, как и курсоры, которых избегали, если не включить слово «курсор» в это решение.Некоторые люди, кажется, просто ненавидят слово, а не механику.

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

  • Продолжить передачу, исключая сбойные клиентские данные в каждой таблице, оставив этих клиентов частично перенесенными, либо
  • прервать всю партию

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

Я не могу вспомнить ни одной ситуации, когда я хотел использовать курсор ниже «верхнего уровня» таких переводов (например, выбирая, какойклиент для передачи следующий)

...