Хранимая процедура SQL Server замедляет каждое выполнение - PullRequest
0 голосов
/ 04 февраля 2012

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

Когда я выполняю процедуру в первый раз, это занимает около 30 секунд. Второе исполнение занимает около 1 минуты. Третье около 2 минут.

Каждое выполнение замедляет процедуру. Теперь это занимает около 10 минут.

Что не так?

Переменные:

declare @StatistikStatus nvarchar(100)
declare @SQL as nvarchar(MAX)
declare @Datum  as nvarchar(50) --Datum im nvarchar Format
declare @Datumdatetime datetime --Datum im datetime Format
declare @tickethistorieID as uniqueidentifier
declare @id int --ID der Terminauswertung. Wird bei Einträgen benötigt, die pro Ticket mehrere Termine vereinbart haben.
declare @nextTermin datetime --Wird bei Einträgen benötigt, die pro Ticket mehrere Termine vereinbart haben.
declare @status nvarchar(100)
declare @statusdiff as nvarchar(100)
declare @vorStatus as nvarchar(100)
declare @lastid as int
declare @tickethistoriemerker nvarchar(40)
declare @statistikstatusmerker nvarchar(100)
DECLARE @TicketID uniqueidentifier

Пример курсора:

DECLARE C_TicketHistorie CURSOR FOR
    SELECT  
        dbo.TicketHistorie.TicketID,dbo.TicketHistorie.Datum,dbo.tickethistorie.tickethistorieid
    FROM 
        dbo.TicketHistorie INNER JOIN
        dbo.Status ON dbo.TicketHistorie.NeueStatusID = dbo.Status.StatusID
        INNER JOIN dbo.StatuszuStatistikStatus as s on s.status_ID = dbo.Status.statusid
        INNER JOIN dbo.StatistikStatus as ss on s.bewertung_id = ss.id
    WHERE     
    ss.id = 5 AND -- 5 = HNR Terminbestätigung
        (dbo.Status.Name = N'Termin vereinbart') 
     AND ((YEAR(dbo.TicketHistorie.Datum) >= 2011 and day(dbo.TicketHistorie.Datum) >= 27 and month(dbo.TicketHistorie.Datum) >= 12)or YEAR(dbo.TicketHistorie.Datum) >= 2012)

    ORDER BY TicketID,Datum asc
OPEN C_TicketHistorie;

FETCH NEXT FROM C_TicketHistorie into @TicketID,@Datumdatetime,@TickethistorieID
WHILE @@FETCH_STATUS = 0
BEGIN
--some inserts etc.
FETCH NEXT FROM C_TicketHistorie into @TicketID,@Datumdatetime,@TickethistorieID
END
CLOSE C_TicketHistorie
DEALLOCATE C_TicketHistorie

У меня есть 4 курсора. И какой-то динамический SQL вроде этого

SET @SQL ='UPDATE Statistik.dbo.terminauswertungab27122011 SET ['
                SET @SQL =@SQL + @StatistikStatus+']='''
                SET @SQL =@SQL + cast(@TicketHistorieID as NVARCHAR(36))+''''
                SET @SQL =@SQL + ' WHERE ID = ' + cast(@ID as nvarchar) +' and ['+@StatistikStatus+'] IS NULL' 
                EXEC (@SQL)

Я вызываю процедуру с использованием SSMS.

в начале stp я удаляю таблицу, в которую вставляются вставки. Затем я делаю вставки. строки таблицы одинаковы при каждом выполнении

1 Ответ

2 голосов
/ 04 февраля 2012

Прежде всего, измените объявление курсора на более эффективный курсор:

DECLARE C_TicketHistorie CURSOR
    LOCAL STATIC FORWARD_ONLY READ_ONLY
    FOR

Далее, вы уверены, что вам нужен курсор для этих операций? Кажется, что ваше обновление, например, могло бы быть выполнено как одна операция на основе набора вместо курсора и динамического SQL, особенно если вы знаете набор имен столбцов, которые могут быть указаны @StatistikStatus (где это определяется, путь?). Вот как можно создать динамическое обновление SQL на основе набора одним махом вместо курсора:

DECLARE @sql NVARCHAR(MAX) = N'';

WITH x AS
(
    SELECT  
        -- why only use aliases for the tables you don't reference often?
        th.TicketID, th.Datum, th.tickethistorieid
    FROM 
        dbo.TicketHistorie AS th
        INNER JOIN dbo.Status AS st
          ON th.NeueStatusID = st.StatusID
        INNER JOIN dbo.StatuszuStatistikStatus as s 
          on s.status_ID = st.statusid
        INNER JOIN dbo.StatistikStatus as ss 
          on s.bewertung_id = ss.id
    WHERE     
      ss.id = 5 -- 5 = HNR Terminbestätigung 
      AND st.Name = N'Termin vereinbart'
     -- be smarter about date range queries!
      AND dbo.TicketHistorie.Datum >= '2011127'
)
SELECT @sql += N'UPDATE Statistik.dbo.terminauswertungab27122011 SET ['
       + @StatistikStatus+']='''
       + cast(@TicketHistorieID as NVARCHAR(36))+''''
       + ' WHERE ID = ' + cast(@ID as nvarchar) + ' -- nvarchar(WHAT)?
       and ['+@StatistikStatus+'] IS NULL;';

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

...