而在sql server中进行一些递归后,循环速度变慢

而在sql server中进行一些递归后,循环速度变慢,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个存储过程,它使用while循环迭代每个记录 然后做一些计算。存储过程具有以下逻辑: 将某些记录从旧\u表插入特定范围的新\u表 780万条记录。插入花了4分钟。 然后将金额大于100的记录复制到临时表中 37000项记录。 在临时表的id列上创建聚集索引。 启动while循环,以迭代temp表total 37000条记录中的每个id列。 对于每个迭代,在while循环中调用一个存储过程。 Sp的工作速度更快,最多可在5分钟内完成5000条记录 但在5000年之后,处理记录的时间有所延迟。

我有一个存储过程,它使用while循环迭代每个记录 然后做一些计算。存储过程具有以下逻辑:

将某些记录从旧\u表插入特定范围的新\u表 780万条记录。插入花了4分钟。 然后将金额大于100的记录复制到临时表中 37000项记录。 在临时表的id列上创建聚集索引。 启动while循环,以迭代temp表total 37000条记录中的每个id列。 对于每个迭代,在while循环中调用一个存储过程。 Sp的工作速度更快,最多可在5分钟内完成5000条记录 但在5000年之后,处理记录的时间有所延迟。延迟发生在处理每100条记录之后。这次延误有什么原因吗

存储过程的示例结构:

use my_db
go

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

IF OBJECT_ID('[dbo].[usp_datacopy]') IS NULL -- Check if SP Exists
EXEC('CREATE PROCEDURE [dbo].[usp_datacopy] AS SET NOCOUNT ON;') -- Create  dummy/empty SP
GO 

ALTER PROCEDURE [dbo].[usp_datacopy]
@Startdate datetime, 
@Enddate   datetime, 
@Percent   int       
AS
BEGIN   
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRAN

DECLARE @PerVal NUMERIC(10,2) = @percent /100.00,--Get the percent value for input.
        @wkstartdate     DateTime,
        @wkenddate       Datetime,
        @OfficeID        int,
        @id              int = 1,
        @spcount        int ,
        @rdate           datetime,


IF OBJECT_ID ('TEMPDB..#temptable') IS NOT NULL
DROP TABLE #temptable 


INSERT INTO [dbo].[new_table]
            ( TimeID, OfficeID, dateval, rHour, Complexity,RowCountval)

        SELECT TimeID + 364, OfficeID,dateadd(dd,364,dateval),rHour, Complexity , RowCountval,
        FROM   [dbo].[old_table] WITH (NOLOCK)
        WHERE  dateval BETWEEN @Startdate  AND @Enddate

 --select Day records with value > 100

SELECT ROW_NUMBER() over(order by timeid) id,TimeID, OfficeID, dateval, rHour, Complexity,RowCountval
 INTO #temptable
 FROM [dbo].[new_table] WITH (NOLOCK)
 WHERE RDATE BETWEEN @wkstartdate AND @wkenddate   
   AND RowCountval  > 100

 CREATE CLUSTERED INDEX id_index on #temptable (id)

 SELECT @spcount  = COUNT (1) from #temptable

 WHILE   @id <= @spcount   --37000 records
 BEGIN

      SELECT @OfficeID    =  officeid    FROM #temptable  WHERE id = @id
      SELECT @rdate       =  dateval     FROM #temptable  WHERE id = @id 

      EXEC CalcPercentforEachRecord @rdate, @OfficeID, @PerVal

      PRINT @ID

      SELECT @id          = @id + 1
      SELECT @OfficeID    = NULL
      SELECT @rdate       = NULL
 END                
 IF @@ERROR = 0
      BEGIN
          COMMIT TRAN;
      END
END TRY
BEGIN CATCH
          SELECT @@ERROR AS ERROR,ERROR_MESSAGE() AS ErrorMessage,ERROR_LINE() AS ErrorLineNo
ROLLBACK TRAN;
END CATCH
SET NOCOUNT OFF;
  END 

请提供您的sp。。。我们没有水晶球:请添加您的执行计划。正如其他评论员所指出的,我们需要更多信息。也就是说,我至少要提到,尽管循环、游标或任何形式的每次记录处理在性能方面对我来说都是一个危险信号。准备从集合的角度思考,并相应地重构代码。有了更多的信息,我们可能会给你一个更简单的解决方案,也可能不会,但我的印象是,这个问题发生在冰层较薄的地区。我们可以得到CalcPercentforEachRecord的代码吗?您还可以将:SELECT OfficeID=OfficeID FROM tettable WHERE id=id选择rdate=dateval FROM tettable WHERE id=id替换为:SELECT OfficeID=OfficeID,rdate=dateval FROM tentable WHERE id=id这样,循环体中只有一个select语句,而不是创建自己的游标,您可以使用游标来迭代临时表,但请记住使用正确的设置,不仅仅是默认值——当然,最好通过彻底折磨row方法来摆脱row。