我有一个存储过程,可以使用一些游标进行许多选择和更新。
当我第一次执行该程序时,大约需要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的开头我删除了插入的表。然后我做了插入。每次执行时表行都是相同的
答案 0 :(得分:2)
首先,将光标声明更改为更高效的光标:
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;';
这里可能会有更多优化,但正如评论所暗示的那样,没有更多信息就很难做到。