Я мог бы вспомнить множество причин, по которым это замедляется, но трудно сузить его, не зная мощности ваших данных.
Случайные наблюдения:
- ВашФункция format_message (), безусловно, собака;все UDFs есть.Но сколько строк вы вставляете за проход?
- @ runningtable_main никогда не очищается.
- обновления дорогие
- удаления дорогие.Если вы используете временные таблицы и переделываете свою реализацию, вы можете усечь вместо удаления
Чтобы самим разобраться в этом, добавьте инструментарий:
DECLARE @now DATETIME, @duration INT, @rowcount INT
WHILE....
-- Fetch new record to be assigned to one of the open declaration sets
FETCH NEXT INTO @row_field1, @row_field2....
IF (@flag2 = 1) AND ((@flag1 = 0) OR (@row_field1 <> @prevrow_field1))
BEGIN
PRINT '---------------'
-- Logging info: we are closing a child declaration set
INSERT INTO @logtable SELECT '--> LOG MESSAGE'
SET @now = GETDATE()
INSERT INTO @logtable
SELECT format_message(@row_field1, @calc_field2, field3...)
FROM @runningtable_sub S LEFT JOIN @runningtable_main M ON S.MainID = M.ID
SELECT @rowcount = @@ROWCOUNT, @duration = DATEDIFF(ms,@now,GETDATE)
RAISERROR('%i row(s) inserted into @logtable, %i milliseconds',-1,-1,@rowcount,@duration) WITH NOWAIT
-- Update enddate of parent
SET @now = GETDATE()
UPDATE M SET M.enddate = DATEADD(day,365,S.enddate)
FROM @runningtable_sub S
LEFT JOIN @runningtable_main M
ON S.MainID = M.ID
SELECT @rowcount = @@ROWCOUNT, @duration = DATEDIFF(ms,@now,GETDATE)
RAISERROR('%i row(s) updated in @runningtable_main, %i milliseconds',-1,-1,@rowcount,@duration) WITH NOWAIT
-- close and save child
SET @now = GETDATE()
INSERT INTO outputtable_main
SELECT @field1, COALESCE(Z.Field1,'NULL'), S.startdate, S.enddate,
M.Startdate, M.Enddate
FROM @runningtable_sub S
LEFT JOIN @runningtable_main M ON S.MainID = M.ID
SELECT @rowcount = @@ROWCOUNT, @duration = DATEDIFF(ms,@now,GETDATE)
RAISERROR('%i row(s) inserted into outputtable_main, %i milliseconds',-1,-1,@rowcount,@duration) WITH NOWAIT
-- delete child from running table
SET @now = GETDATE()
DELETE FROM @runningtable_sub WHERE S.enddate < @curdate
SELECT @rowcount = @@ROWCOUNT, @duration = DATEDIFF(ms,@now,GETDATE)
RAISERROR('%i row(s) deleted from @runningtable_sub, %i milliseconds',-1,-1,@rowcount,@duration) WITH NOWAIT
END
Если вы включилиВесь код (включая объявление курсора), а не просто символический отрывок, кто-то здесь, возможно, мог бы переработать, чтобы вы были намного эффективнее и / или избегали использования курсоров вместе.