Я могу понять желание избежать использования курсора из-за накладных расходов и неудобств, но похоже, что происходит серьезная мания фобии курсора, когда люди делают все возможное, чтобы избежать необходимости его использовать.
Например, был задан один вопрос, как сделать что-то очевидно тривиальное с курсором, и принятый ответ, предложенный с использованием рекурсивного запроса общего табличного выражения (CTE) с рекурсивной настраиваемой функцией, хотя это ограничивает количество строк, которые могут быть обработаны, до 32 (из-за ограничения рекурсивного вызова функции на сервере sql). Это кажется мне ужасным решением проблемы долговечности системы, не говоря уже о огромных усилиях, направленных на то, чтобы избежать использования простого курсора.
В чем причина такой безумной ненависти? Издал ли какой-нибудь «авторитетный авторитет» фетву против курсоров? Неужели в сердце курсоров таится какое-то невыразимое зло, которое развращает нравы детей или что-то в этом роде?
Вопрос вики, больше интересующий ответ, чем представитель.
Связанная информация:
Курсоры быстрой перемотки SQL Server
РЕДАКТИРОВАТЬ: позвольте мне быть более точным: я понимаю, что курсоры не должны использоваться вместо обычных реляционных операций ; это и ежу понятно. Чего я не понимаю, так это то, что люди стараются изо всех сил избегать курсоров, как будто у них есть кути или что-то в этом роде, даже когда курсор является более простым и / или более эффективным решением. Меня сбивает с толку иррациональная ненависть, а не очевидная техническая эффективность.
32
- нонсенс. Предположительно вы думаете о рекурсивных триггеров и максимум@@NESTLEVEL
из32
. Его можно задать в запросеOPTION (MAXRECURSION N)
со значением по умолчанию100
и без0
ограничений.Ответы:
«Накладные расходы» на курсоры - это просто часть API. Курсоры - это то, как части СУБД работают под капотом. Часто
CREATE TABLE
и операторыINSERT
имеютSELECT
, и их реализация является очевидной внутренней реализацией курсора.Использование высокоуровневых «операторов на основе наборов» объединяет результаты курсора в единый набор результатов, что означает меньшее количество операций API вперед и назад.
Курсоры предшествуют современным языкам, которые предоставляют первоклассные коллекции. В старых версиях C, COBOL, Fortran и т. Д. Приходилось обрабатывать строки по одной, потому что не было понятия «коллекция», которое можно было бы широко использовать. Java, C #, Python и т. Д. Имеют первоклассные структуры списков, содержащие наборы результатов.
Медленный выпуск
В некоторых кругах реляционные соединения являются загадкой, и люди будут писать вложенные курсоры, а не простое соединение. Я видел поистине эпические операции вложенного цикла, записанные в виде множества курсоров. Победить оптимизацию РСУБД. И работает очень медленно.
Простое переписывание SQL для замены вложенных циклов курсора объединениями, а единственный плоский цикл курсора может заставить программы работать в 100 раз быстрее. [Они думали, что я бог оптимизации. Все, что я сделал, это заменил вложенные циклы на соединения. Все еще используются курсоры.]
Эта путаница часто приводит к обвинению в использовании курсоров. Однако проблема не в курсоре, а в неправильном использовании курсора.
Проблема размера
Для действительно эпических наборов результатов (например, выгрузки таблицы в файл) курсоры необходимы. Операции на основе наборов не могут материализовать действительно большие наборы результатов в виде единой коллекции в памяти.
альтернативы
Я стараюсь как можно больше использовать слой ORM. Но это преследует две цели. Во-первых, курсоры управляются компонентом ORM. Во-вторых, SQL отделяется от приложения в файл конфигурации. Дело не в том, что курсоры плохие. Дело в том, что кодирование всех этих открытий, закрытий и выборок не является дополнительным программированием.
источник
Курсоры заставляют людей чрезмерно применять процедурный образ мышления к среде, основанной на наборах.
И они МЕДЛЕННЫЕ !!!
От SQLTeam :
источник
Выше есть ответ, в котором говорится, что «курсоры - САМЫЙ МЕДЛЕННЫЙ способ доступа к данным внутри SQL Server ... курсоры более чем в тридцать раз медленнее, чем альтернативы на основе набора».
Это утверждение может быть верным при многих обстоятельствах, но как общее заявление оно проблематично. Например, я хорошо использовал курсоры в ситуациях, когда я хочу выполнить операцию обновления или удаления, затрагивающую многие строки большой таблицы, которая получает постоянные производственные чтения. Выполнение хранимой процедуры, которая выполняет эти обновления по одной строке за раз, в конечном итоге оказывается быстрее, чем операции на основе наборов, потому что операция на основе набора конфликтует с операцией чтения и в конечном итоге вызывает ужасные проблемы с блокировкой (и может полностью убить производственную систему, в крайнем случае).
В отсутствие других действий с базой данных операции с наборами всегда выполняются быстрее. В производственных системах это зависит.
источник
Курсоры обычно используются начинающими разработчиками SQL в тех местах, где операции на основе наборов были бы лучше. В частности, когда люди изучают SQL после изучения традиционного языка программирования, менталитет «повторять эти записи» имеет тенденцию приводить людей к неправильному использованию курсоров.
Самые серьезные книги по SQL включают главу, в которой говорится об использовании курсоров; хорошо написанные дают понять, что курсоры имеют свое место, но не должны использоваться для операций, основанных на наборах.
Очевидно, существуют ситуации, когда курсоры - правильный выбор или, по крайней мере, правильный выбор.
источник
Оптимизатор часто не может использовать реляционную алгебру для преобразования проблемы, когда используется метод курсора. Часто курсор - отличный способ решить проблему, но SQL - это декларативный язык, и в базе данных содержится много информации, от ограничений до статистики и индексов, что означает, что у оптимизатора есть много вариантов для решения проблемы. проблема, тогда как курсор явно указывает решение.
источник
В Oracle PL / SQL курсоры не приводят к блокировкам таблиц, и можно использовать массовый сбор / массовую выборку.
В Oracle 10 часто используемый неявный курсор
неявно выбирает 100 строк за раз. Также возможен явный массовый сбор / массовая выборка.
Однако курсоры PL / SQL - это последнее средство, используйте их, когда не можете решить проблему с помощью SQL на основе наборов.
Другая причина - это распараллеливание: базе данных проще распараллеливать большие операторы на основе наборов, чем построчный императивный код. По этой же причине функциональное программирование становится все более популярным (Haskell, F #, Lisp, C # LINQ, MapReduce ...), функциональное программирование упрощает распараллеливание. Число процессоров на компьютер растет, поэтому распараллеливание становится все более серьезной проблемой.
источник
В общем, поскольку в реляционной базе данных производительность кода с использованием курсоров на порядок хуже, чем у операций на основе наборов.
источник
В приведенных выше ответах недостаточно подчеркивается важность блокировки. Я не большой поклонник курсоров, потому что они часто приводят к блокировкам на уровне таблицы.
источник
Как бы то ни было, я прочитал, что «одно» место, где курсор будет выполнять, его аналог, основанный на наборе, - это промежуточный итог. В небольшой таблице скорость суммирования строк по порядку по столбцам благоприятствует операции на основе наборов, но по мере увеличения размера строки в таблице курсор будет становиться быстрее, потому что он может просто переносить значение промежуточной суммы на следующий проход петля. Другой аргумент в том, где вы должны сделать промежуточную сумму ...
источник
Я согласен со статьей на этой странице:
http://weblogs.sqlteam.com/jeffs/archive/2008/06/05/sql-server-cursor-removal.aspx
источник
Помимо проблем с производительностью (не), я думаю, что самый большой недостаток курсоров - их болезненная отладка. Особенно по сравнению с кодом в большинстве клиентских приложений, где отладка имеет тенденцию быть сравнительно простой, а языковые функции гораздо проще. Фактически, я утверждаю, что почти все, что делается в SQL с помощью курсора, вероятно, должно происходить в первую очередь в клиентском приложении.
источник
Можете ли вы опубликовать этот пример курсора или ссылку на вопрос? Возможно, есть способ лучше, чем рекурсивный CTE.
В дополнение к другим комментариям, курсоры при неправильном использовании (что часто бывает) вызывают ненужные блокировки страниц / строк.
источник
Вы, вероятно, могли бы закончить свой вопрос после второго абзаца, вместо того, чтобы называть людей «сумасшедшими» просто потому, что у них другая точка зрения, чем у вас, и как-то иначе пытаться высмеивать профессионалов, у которых могут быть очень веские причины чувствовать то же самое.
Что касается вашего вопроса, хотя, безусловно, существуют ситуации, в которых может потребоваться курсор, по моему опыту разработчики решают, что курсор «должен» использоваться ДАЛЬШЕ чаще, чем на самом деле. На мой взгляд, вероятность того, что кто-то ошибется в том, что курсоры будут слишком частыми, по сравнению с тем, что они не будут использоваться, когда должны, НАМНОГО выше.
источник
в основном 2 блока кода, которые делают то же самое. может быть, это немного странный пример, но он подтверждает суть дела. SQL Server 2005:
одно обновление занимает 156 мс, а курсора - 2016 мс.
источник