Подтвердить что ты не робот

MS SQL Server - Когда хороший CURSOR?

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

Все, что я прочитал, говорит, что КУРСОРЫ ужасны, вызывают ненужную блокировку и т.д., и тестирование производительности доказывает то же самое.

Мой вопрос в том, когда вы используете КУРСОР и в каких ситуациях они полезны или хороши?

Если нет смысла, зачем им создавать такую ​​плохую структуру/тип управления для SQL?

4b9b3361

Ответ 1

Обычно их следует избегать, но функция существует по какой-то причине, и есть время их использовать. Я бы сказал, что 90%% курсоров, которые я видел, не нужны. Если вы используете их для операций CRUD, которые можно почти всегда переделывать с помощью набора. Я часто видел, что люди используют курсоры для этого, потому что они не знают, как использовать объединения в обновлении или удалении, или что они могут использовать выбранную статуту вместо предложения значений в вставке. Другое ненужное использование, когда люди думают, что они нуждаются в них для немного более сложной обработки, которая на самом деле может быть легко обработана с помощью оператора case.

Курсоры иногда быстрее вычисляют что-то вроде текущей.

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

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

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

Ответ 2

Я спросил парня в команде SQL Server один раз, если бы вы могли добавить одну функцию, которая сделает продукт лучше для всех, каков он будет?

Его ответ был "Добавить? Ха, я бы забрал его. Если вы избавитесь от курсоров, вы заставите программистов по всему миру начать думать о вещах на основе SET, и это будет самый большой в мире рост производительности БД, который вы когда-либо увидите".

В свою очередь, я, как правило, вижу шаблон, похоже, много процедурных кодеров, которые используют курсоры, потому что они должны иметь возможность выполнять операцию по одному элементу за раз и пропустить концепцию цикла WHILE старой моды. Такая же основная идея без курсора над головой. Все еще не так быстро и эффективно, как что-то SET, но в 90% случаев, когда кто-то утверждает: "Я не могу сделать этот набор на основе, я должен использовать курсоры", я могу заставить их сделать это с помощью цикла while.

Ответ 4

Руководство по подготовке MCTS для SQL Server 2008, которое я изучаю, рекомендует использовать внешний код CLR везде, где CURSOR потребуется в T-SQL, особенно теперь, когда SQL Server 2008 поддерживает настраиваемые функции агрегации.

5 лет назад я работал с ними для создания широких функций отчетности, но я не думаю, что теперь я могу придумать для них хороший вариант использования. Агрегаты и функции CLR выполняют аналогично встроенным агрегатным функциям.

Ответ 5

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

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

Ответ 6

OMG, как я забыл о Группе? Я взял запрос на основе курсора, который вы видите ниже, и заменил его на тот, который после него. Теперь я получаю единый результирующий набор, поэтому нет проблем с использованием sqlsrv_next_result() в php.

DECLARE @thisday datetime;

DECLARE daycursor CURSOR FOR
SELECT DISTINCT DATEADD(day, 0, DATEDIFF(day, 0, TimeCollected)) as thisday
FROM computerusedata

OPEN daycursor;
FETCH NEXT FROM daycursor
INTO @thisday;
WHILE @@FETCH_STATUS = 0
    BEGIN
    select distinct left(ComputerName,5) as CompGroup,DATEADD(day, 0, DATEDIFF(day, 0, TimeCollected)) as day
    FROM computerusedata
    where DATEADD(day, 0, DATEDIFF(day, 0, TimeCollected)) = @thisday
    order by CompGroup;
    FETCH NEXT FROM daycursor;
    END;
CLOSE daycursor;
DEALLOCATE daycursor;";


select DATEADD(day, 0, DATEDIFF(day, 0, TimeCollected)) as day,left(ComputerName,5) as CompGroup
from ComputerUseData
group by DATEADD(day, 0, DATEDIFF(day, 0, TimeCollected)),left(ComputerName,5)
order by day,CompGroup

Ответ 7

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

Ответ 8

Курсоры полезны, когда 1) вам нужно сделать что-то, что вы не можете сделать с заданной операцией, или 2) не имеет смысла делать одну и ту же работу, делая итеративные вызовы из прикладного уровня. Или иногда у вас есть процедура, которая должна оставаться на уровне базы данных, и вы просто не можете отлаживаться в средстве потока приложения, чтобы перебирать некоторый набор результатов.

Одна рекомендация, которую я хотел бы сделать, заключается в том, что люди используют переменные курсора, а не обычные курсоры, потому что вы избегаете проблем размещения/освобождения курсора, которые окружают обычные курсоры. При нормальном курсоре, если вы не освободите их, они сохраняются, что может стать источником утечки памяти. Не так с курсорами на основе переменных (т.е. DECLARE @cursor CURSOR).

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

Ответ 9

Вы используете курсор для перестройки или реорганизации табличных индексов отдельно
если нет способа запустить ALTER INDEX... как операцию на основе набора.