Курсоры SQL ... Какие варианты использования вы бы защищали? - PullRequest
2 голосов
/ 05 октября 2008

Я пойду первым.

Я на 100% в лагере операций с сетами. Но что происходит, когда установлена ​​логика на всем желаемом входном домене приводит к такому большому поиску, что запрос значительно замедляется, приходит в обход или в основном занимает бесконечное время?

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

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

Ответы [ 10 ]

3 голосов
/ 06 октября 2008

Существует множество различных вариантов поведения курсора .

  • STATIC vs KEYSET vs DYNAMIC
  • СВИТОК - ВПЕРЕД И ТОЛЬКО ВПЕРЕД
  • НЕДОСТАТОЧНО или нет
  • ОПТИМАЛЬНО или ЧИТАЙТЕ ТОЛЬКО или нет
  • МЕСТНЫЙ против ГЛОБАЛЬНОГО (по крайней мере, это легко)

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

И так, я никогда не делаю.

Вместо этого, когда я испытываю желание зацикливаться на чем-то в T-SQL ... Я загружаю это в таблицу переменных, которая похожа на курсор LOCAL STATIC SCROLL ... за исключением того, что его можно проиндексировать и объединить редактировать: и обратная сторона предотвращения использования параллелизма).

3 голосов
/ 06 октября 2008

У меня есть много случаев, когда строки из таблицы конфигурации должны быть прочитаны, а код сгенерирован и выполнен, или во многих сценариях метапрограммирования.

Есть также случаи, когда курсоры просто выигрывают, потому что оптимизатор недостаточно умен. В этих случаях либо в вашей голове есть метаинформация, которая просто не раскрывается оптимизатору через индексы или статистику таблиц, либо код настолько сложен, что объединения (и, как правило, повторные объединения) просто могут Не оптимизируйте их так, как вы можете визуализировать их курсором. Я полагаю, что в SQL Server 2005 CTE, как правило, делают этот код намного проще в коде, но трудно ли понять, оптимизатор также считает их более простыми - это сводится к сравнению плана выполнения с тем, как, по вашему мнению, это можно сделать. наиболее эффективно и совершая звонок.

Общее правило - не используйте курсор без необходимости. Но когда это необходимо, не беспокойтесь об этом.

2 голосов
/ 06 октября 2008

Наряду с тем, что Дэвид Б сказал, я тоже предпочитаю подход "цикл / таблица".

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

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

2 голосов
/ 06 октября 2008

Конечно, есть ряд мест, где курсоры могут быть лучше, чем операции на основе множеств.

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

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

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

2 голосов
/ 06 октября 2008

Очень редко вы получаете операцию, для которой нужен курсор, но в T-SQL это довольно редко. Столбцы или последовательности Identity (int) упорядочивают вещи в операциях над множествами. Агрегации, в которых вычисления могут меняться в определенных точках (например, накапливать заявки от основания до предела или превышения), являются процедурными по своей сути, поэтому они являются кандидатом в курсор.

Другие кандидаты были бы по своей сути процедурными, такими как циклическое переключение таблицы конфигурации и генерация и выполнение серии запросов.

2 голосов
/ 06 октября 2008

В чистой среде SQL я бы предпочел избегать курсоров, как вы предлагаете. Но как только вы переходите на процедурный язык (например, PL / SQL), есть ряд применений. Например, если вы хотите извлечь определенные строки и хотите «сделать» что-то более сложное, чем обновить их вместе с ними.

1 голос
/ 04 марта 2009

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

Промежуточные суммы, как обсуждали другие, могут быть быстрее.

Если вы отправляете электронное письмо из базы данных (не самая лучшая идея, но иногда это то, с чем вы застряли), то курсор может гарантировать, что клиент a не увидит адрес электронной почты клиента b, когда вы отправляете оба сообщения.

0 голосов
/ 07 октября 2008

Если таблица по какой-либо причине не проиндексирована, курсор будет быстрее, чем другие методы итерации по таблице. Я нашел эту информацию в этом блоге о курсорах в SQL Server в прошлом году.

Хотя автор выступает за подход «использовать только в качестве крайней меры» (как и все здесь), она находит один или два случая, когда работают курсоры, а также другие доступные альтернативы (включая промежуточные итоги, указанные Роберт Россни). Среди других интересных моментов, которые она подчеркивает, она указывает, что курсоры работают более эффективно внутри хранимых процедур, чем в виде специальных запросов. Автор также отлично указывает, когда начинают возникать проблемы с производительностью, которые мы все ассоциируем с курсорами.

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

0 голосов
/ 06 октября 2008

Необходимость использования курсора, как правило, является признаком того, что вы делаете в базе данных то, что должно быть сделано в приложении. Как уже говорили другие, курсоры, как правило, необходимы, когда хранимая процедура вычисляет промежуточные суммы или когда вы генерируете код и / или метапрограммирование.

Но почему вы выполняете такую ​​работу в хранимой процедуре? Это действительно лучшее использование вашего сервера базы данных? Является ли T-SQL действительно правильным языком для генерации кода?

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

0 голосов
/ 06 октября 2008

Хорошо, одна операция, где курсоры лучше, чем наборы, - это вычисление промежуточного итога и подобных вещей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...