Оптимизация курсора и хранимой процедуры - PullRequest
3 голосов
/ 29 ноября 2011

Следующий сохраненный процесс был написан некоторое время назад и теперь требует модификации.

Невозможно связаться с первоначальным разработчиком, я посмотрел. Мне этот процесс кажется слишком сложным. Разве это не может быть сделано с простым ОБНОВЛЕНИЕМ? Кто-нибудь может оправдать использование CURSOR здесь?

ALTER PROCEDURE [settle_Stage1]
    @settleBatch int
AS

DECLARE @refDate datetime;
DECLARE @dd int;
DECLARE @uid int;

DECLARE trans_cursor CURSOR FOR 
SELECT uid, refDate FROM tblTransactions WHERE (settle IS NULL ) AND (state IN (  21, 31, 98, 99 ))
OPEN trans_cursor
FETCH FROM trans_cursor INTO @uid, @refDate
WHILE @@FETCH_STATUS = 0
   BEGIN
    SET @dd = DATEDIFF( day, @refDate, getDate())
    IF ( @dd >= '1' )
      BEGIN
        UPDATE tblTransactions
        SET settle = @settleBatch WHERE uid = @uid
      END
    FETCH FROM trans_cursor INTO @uid, @refDate
   END  
CLOSE trans_cursor
DEALLOCATE trans_cursor

Ответы [ 4 ]

6 голосов
/ 29 ноября 2011

Вы правы - это похоже на "процедурный SQL" от кого-то, кто, вероятно, не получает SQL и не выполняет операции над множествами.

И преобразование этого в запрос на основе множеств должно повысить производительность.

Курсор не нужен и действительно слишком усложняет хранимую процедуру.

4 голосов
/ 29 ноября 2011

Просто глядя на это, я не вижу никакой причины, почему это не делается ни за одно ОБНОВЛЕНИЕ.Возможно (и это maaaaaybe), если слишком много записей для обновления, то это может быть причиной.В любом случае, я просто изменил бы это с помощью:

UPDATE tblTransactions
SET settle = @settleBatch
WHERE settle IS NULL 
AND [state] IN (21, 31, 98, 99)
AND DATEDIFF( day, refDate, getDate()) >= 1

отредактировано после комментария @Martin Smith

4 голосов
/ 29 ноября 2011

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

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

ПРИМЕЧАНИЕ: Я не защищаю этот метод, я толькопредлагая причины.

1 голос
/ 29 ноября 2011

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

...