Хранимая процедура слишком медленная (с использованием CURSOR)
У меня есть код ниже, чтобы вставить необработанный (processed=0
) записи с сервера 1 на сервер 2 (с использованием связанных серверов), и после вставки его следует обновить до processed=1
Я просто использовал
Запрос 1:
INSERT INTO SELECT FROM WHERE processed=0
UPDATE processed=1 WHERE processed=0
Запрос 2:
DECLARE pending_records CURSOR LOCAL FOR
SELECT FROM WHERE processed=0
OPEN pending_records
FETCH NEXT FROM pending_records INTO @UniqueID
WHILE @@FETCH_STATUS=0
BEGIN
INSERT INTO SELECT FROM WHERE UniqueID=@UniqueID
IF @@ROWCOUNT=1 .... UPDATE processed=1 WHERE UniqueID=@UniqueID
FETCH NEXT FROM pending_records INTO @UniqueID
END
CLOSE pending_records
DEALLOCATE pending_records
Запрос 1 очень быстрый, а запрос с использованием курсора слишком медленный (для обновления 1 записи требуется 30 секунд)
Я держусь подальше от Query 1, потому что, если в базе данных произойдет сбой, это повлияет на записи. Примечание: я не могу использовать DISTRIBUTED TRANSACTION
прямо сейчас, потому что это требует дополнительной настройки.
2 ответа
Вы пытались использовать аргумент FAST_FORWARD?
"FAT_FORWARD" определяет курсор FORWARD_ONLY, READ_ONLY с включенной оптимизацией производительности. FAST_FORWARD не может быть указан, если также указаны SCROLL или FOR_UPDATE.
Узнайте больше здесь.
Вы можете попробовать это: добавить дополнительный столбец в вашу таблицу, где вы добавили дополнительный флаг обработки. Сгенерируйте GUID в начале вашей хранимой процедуры и обновите таблицу:
UPDATE <table>
SET processing_flag = <GUID>
WHERE processed = 0;
И тогда вы можете просто перенести ваши строки на другой сервер с помощью
INSERT INTO <target>
SELECT <columns>
FROM <source>
WHERE processed = 0 AND processing_flag = <GUID>;
После этого вы можете установить значение = 1 и удалить флаг_обработки. Если что-то не получается, вы можете выбрать все непереданные строки, обработанные = 0 и processing_flag!= NULL.
У меня была похожая проблема с переносом отдельных строк. Объединяя их все в одну, моя проблема была решена.
Может быть, ваш целевой сервер или соединение слишком медленное.