【发布时间】:2016-02-13 07:17:24
【问题描述】:
我有一个使用 while 循环临时表和游标的存储过程,通过它我可以获得客户的老化余额,但是我的 SP 工作正常,但我有一些性能问题,因为它需要 15 秒才能从一个小的数据块。我正在寻找一种更有效的方法来做到这一点。
提前致谢。
这是我的存储过程。
CREATE TABLE #Customer_Temp (
AccountCode varchar(50),
AccountTitle varchar(50),
CurrentBalance int,
FirstBalance int,
SecondBalance int,
ThirdBalance int,
FourthBalance int,
FifthBalance int,
SixthBalance int,
SeventhBalance int,
EighthBalance int,
OpeningBalance int
)
INSERT INTO #customer_temp (AccountCode, AccountTitle, OpeningBalance)
SELECT
Customer.AccountCode,
Customer.Name,
COA.OpeningBalance
FROM Customers AS Customer
INNER JOIN ChartOfAccount AS COA
ON COA.CompanyId = @Companyid
AND COA.BusinessUnitId = @BusinessUnitId
AND COA.ChartAccount = Customer.AccountCode
--Create Table And Duplicate Customers Data In it ENDED
DECLARE @DrAmount AS int
DECLARE @CrAmount AS int
DECLARE @Balance AS int
DECLARE @FBalance AS int
DECLARE @SBalance AS int
DECLARE @TBalance AS int
DECLARE @FoBalance AS int
DECLARE @FIBalance AS int
DECLARE @SIBalance AS int
DECLARE @SEBalance AS int
DECLARE @EBalance AS int
DECLARE @FSDate AS date
DECLARE @FLDate AS date
DECLARE @SSDate AS date
DECLARE @SLDate AS date
DECLARE @TSDate AS date
DECLARE @TLDate AS date
DECLARE @FOSDate AS date
DECLARE @FOLDate AS date
DECLARE @FISDate AS date
DECLARE @FILDate AS date
DECLARE @SISDate AS date
DECLARE @SILDate AS date
DECLARE @SESDate AS date
DECLARE @SELDate AS date
DECLARE @ESDate AS date
SET @FSDate = DATEADD(DAY, -1, @StartDate)
SET @FLDate = DATEADD(DAY, -6, @FSDate)
SET @SSDate = DATEADD(DAY, -1, @FLDate)
SET @SLDate = DATEADD(DAY, -6, @SSDate)
SET @TSDate = DATEADD(DAY, -1, @SLDate)
SET @TLDate = DATEADD(DAY, -14, @TSDate)
SET @FOSDate = DATEADD(DAY, -1, @TLDate)
SET @FOLDate = DATEADD(DAY, -14, @FOSDate)
SET @FISDate = DATEADD(DAY, -1, @FOLDate)
SET @FILDate = DATEADD(DAY, -14, @FISDate)
SET @SISDate = DATEADD(DAY, -1, @FILDate)
SET @SILDate = DATEADD(DAY, -29, @SISDate)
SET @SESDate = DATEADD(DAY, -1, @SILDate)
SET @SELDate = DATEADD(DAY, -89, @SESDate)
SET @ESDate = DATEADD(DAY, -1, @SELDate)
DECLARE @TempCCode AS varchar(50)
DECLARE @TempOBalance AS float
DECLARE CustomerCursor CURSOR FOR
SELECT
AccountCode,
OpeningBalance
FROM #Customer_Temp
OPEN CustomerCursor
FETCH NEXT FROM CustomerCursor INTO @TempCCode, @TempOBalance
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC @FBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@FSDate,
@FLDate,
@Fyear
EXEC @SBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@SSDate,
@SLDate,
@Fyear
EXEC @TBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@TSDate,
@TLDate,
@Fyear
EXEC @FoBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@FOSDate,
@FOLDate,
@Fyear
EXEC @FIBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@FISDate,
@FILDate,
@Fyear
EXEC @SIBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@SISDate,
@SILDate,
@Fyear
PRINT @SESDate
PRINT @SELDate
EXEC @SEBalance =
GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@SESDate,
@SELDate,
@Fyear
EXEC @EBalance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@ESDate,
@EndDate,
@Fyear
EXEC @Balance = GetBalanceOfAgingOnDate @BusinessUnitId,
@Companyid,
@TempCCode,
@StartDate,
@EndDate,
@Fyear
UPDATE #Customer_Temp
SET CurrentBalance = (@Balance + @TempOBalance),
FirstBalance = @FBalance,
SecondBalance = @SBalance,
ThirdBalance = @TBalance,
FourthBalance = @FoBalance,
FifthBalance = @FIBalance,
SixthBalance = @SIBalance,
SeventhBalance = @SEBalance,
EighthBalance = @EBalance
WHERE AccountCode = @TempCCode
FETCH NEXT FROM CustomerCursor INTO @TempCCode, @TempOBalance
END
CLOSE CustomerCursor
DEALLOCATE CustomerCursor
这里是游标中调用的存储过程
CREATE PROCEDURE [dbo].[GetBalanceOfAgingOnDate]
@BusinessUnitId int,
@Companyid int,
@ChartAccount as varchar (50),
@StartDate as DateTime,
@EndDate as DateTime,
@Fyear as varchar(50)
AS BEGIN
Declare @DrAmount as int
Declare @CrAmount as int
Declare @Balance as int
set @DrAmount=(select sum(Dr_Amount) from AccountVocherMaster AS AM ,
AccountVocherChild AS AC Where AM.CompanyId = @Companyid AND
AM.BusinessUnitId = @BusinessUnitId AND AM.FYear = @Fyear AND
AM.VocherId = AC.VocherId AND AC.AccountCode=@ChartAccount AND
AC.CreatedOn Between @EndDate AND @StartDate);
set @CrAmount=(select sum(Cr_Amount) from AccountVocherMaster AS AM ,
AccountVocherChild AS AC Where AM.CompanyId = @Companyid AND
AM.BusinessUnitId = @BusinessUnitId AND AM.FYear = @Fyear AND
AM.VocherId = AC.VocherId AND AC.AccountCode=@ChartAccount AND
AC.CreatedOn Between @EndDate AND @StartDate);
set @Balance = @DrAmount - @CrAmount ;
return ISNULL(@Balance,0)
END
【问题讨论】:
-
嗯,很明显,去掉光标和程序。将其作为基于集合而不是基于行来处理。
-
正如 JamesZ 所避免的那样,循环和游标通常很慢。此外,如果不知道里面的那些存储过程是如何编写的,你就不能排除它们成为瓶颈。也许您可以扩展您要完成的工作,如果没有该上下文,这可能是一个非常大的讨论,涉及逐个分解您的查询。
-
@Nicarus 我已经添加了有问题的调用存储过程,请帮助我问候
-
"!help me" 翻译为“我不知道如何编写 SQL,所以你告诉我如何让它更快(JamesZ 做到了),现在我希望你为我编写代码免费”?错误的网站。让我们结束这个 - 我们不是代码编写服务。
-
我投票结束这个问题,因为我们不是代码编写服务。 OP 显然已经要求我们完全解决他的问题,准备好复制粘贴,而不是解释问题并教育他如何改进他的代码。
标签: sql sql-server performance stored-procedures