Frage

i have a Problem with my performance on this procedure. I am useing MS SQL SERVER 2012 Standard and SSMS on i7 with 8 GB. The OS is Windows Server 2008. The procedure I wrote, are able to Insert or Update Values in the SQL Table between two Times and Dates. For Example

  1. The Procedure Inserts/Update Values between 00:45 AM and 02:45 AM between 01.01.2014 and 01.12.2014.
  2. The Procedure Inserts/Update Values between 00:00 AM and 23:45 PM between 01.01.2014 and 01.12.2014.

For this Procedure, the Important Parameters are

@startdate @Starttime and @enddate @endtime

For Example 01.01.2014 00:00 - 01.12.2014 23:45 / 11 Month. Its quite necessary that the Inputs in the SQL Table are every 15 minutes.

4*24*30*11 = 31580 Values for 11 Month. This take some time.

More than 6 Minutes !

All Threads from the OS are used, if I execute the procedure.

How can I get my slow procedure smarter and faster?

USE [DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
    ALTER PROCEDURE [dbo].[Insert_Into]
    -- parameters for the stored procedure
    @id int,
    @StartDate date,
    @EndDate date,
    @Starttime time,
    @Endtime time,
    @value int

AS

DECLARE @TempTime time = @Starttime
BEGIN
SET NOCOUNT ON;
WHILE @Startdate <= @EndDate
BEGIN


WHILE @Starttime <= @Endtime

BEGIN

--If the entry exisits than update, if not, than insert
if exists (select date,ID from [dbo].[Insert_Table] where Datum = @StartDate + cast(@Starttime as datetime)  AND ID = @id)
begin
    PRINT @Starttime
    UPDATE [dbo].[Insert_Table]
    SET [ID] = @id, [datum] =( @StartDate + cast(@Starttime as datetime)), [value] = @value
    WHERE ID = @id AND Datum =( @StartDate+ cast(@Starttime as datetime))
    IF( @Starttime = @Endtime)
    begin
    print'EndDay'
    SET @Starttime = DATEADD(Minute,1,@Endtime) -- Starttime One Minute over Endtime 
    end
    else
    select @Starttime = DATEADD(MINUTE,15,@Starttime)

end
else
begin

    INSERT INTO  [dbo].[Insert_Table]([ID],[date],[value])
     VALUES
           (@id, @StartDate + cast(@Starttime as datetime), @value )
IF( @Starttime = @Endtime)
    begin
    --print'EndDay'
    SET @Starttime = DATEADD(Minute,1,@Endtime) -- Starttime one minute over Endtime
    end
    else
    Select @Starttime = DATEADD(MINUTE,15,@Starttime)
end

END
--PRINT 'END'
SET @Starttime = @Temptime
Select @StartDate = DATEADD(DAY,1,@StartDate)

END

END
War es hilfreich?

Lösung

Use a CTE, do a UNION ALL on it, this will create a cursive loop that is MUCH better performing than your loop. Look here Using CTE as a block loop ?

Andere Tipps

Thanks a lot ! Great, thats what i looking for !

There is my New Code with CTE

USE DB
declare @StDate datetime = '01/01/2013 00:00.000'
declare @Enddate datetime = '01/06/2014 23:45.000'
declare @value as int = 400
declare @id as int = 999

;with cte as
(
 select DATEADD(MONTH,DATEDIFF(MONTH,0,@StDate),0) as Sdate 
 union all
 select DATEADD(MINUTE,15,SDate) from cte where SDate < @Enddate
 )

Insert into Insert_Table(Date,Value,id)(select SDate as Date, @value,@id from cte )

OPTION (maxrecursion 0)

Select * from Insert_Table order by Date ASC
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top