我想优化下面使用的游标的性能,或者部署一些其他方法来实现所需的结果,这比下面使用的游标快得多。目前,光标能够在5分钟内对1000个客户进行操作,这导致每月平均约250,000个客户的运行时间为1250分钟(每月)。
我正在使用Microsoft SQL Server 2008 R2进行练习。光标位于每月运行的过程中。该过程的month参数是@month_key(datetime变量),它未在下面给出的代码中声明。请记住,该过程需要运行10年的数据,下面的代码是程序运行中最耗时的部分。
--DECLARING VARIABLES
DECLARE @EVENT_12_MONTH_FLAG DATETIME;
DECLARE @I INT;
DECLARE @CUSTOMER INT;
DECLARE @START_DATE DATETIME;
DECLARE @EVENT_FLAG INT;
DECLARE @EVENT_CURSOR CURSOR;
---CURSOR
SET @EVENT_CURSOR = CURSOR FOR
SELECT DISTINCT CUSTOMER_NO
FROM EVENT_DRV
OPEN @EVENT_CURSOR;
FETCH NEXT FROM @EVENT_CURSOR INTO
@CUSTOMER;
--EVENT FLAG
SET @EVENT_FLAG = (SELECT CASE WHEN DEF_FLAG = 1 THEN 1
WHEN (YEAR(A.MONTH_KEY) = YEAR(WRT_OFF_DTE) and MONTH(A.MONTH_KEY) = MONTH(WRT_OFF_DTE)) THEN 1
WHEN DATEDIFF(MONTH,A.MONTH_KEY,WRT_OFF_DTE) = 1 THEN 1 ELSE 0 END
FROM EVENT_DRV A INNER JOIN EVENT_VAR B ON A.CUSTOMER_NO = B.CUSTOMER_NO AND A.MONTH_KEY = B.MONTH_KEY
WHERE A.CUSTOMER_NO=@CUSTOMER AND A.MONTH_KEY = DATEADD(MONTH,-12,@MONTH_KEY))
WHILE @@FETCH_STATUS = 0
BEGIN
SET @I =12;
WHILE (@I >=0)
BEGIN
SET @I=@I-1 ;
SET @START_DATE=DATEADD(MONTH,-@I, @MONTH_KEY)
SET @EVENT_12_MONTH_FLAG = (SELECT CASE WHEN YEAR(A.MONTH_KEY) = YEAR(DEF_MONTH_1) AND MONTH(A.MONTH_KEY) = MONTH(DEF_MONTH_1) THEN 1
WHEN (YEAR(A.MONTH_KEY) = YEAR(WRT_OFF_DTE) and MONTH(A.MONTH_KEY) = MONTH(WRT_OFF_DTE)) THEN 1
WHEN DATEDIFF(MONTH,A.MONTH_KEY,WRT_OFF_DTE) = 1 THEN 1 ELSE 0
END
FROM EVENT_DRV A INNER JOIN EVENT_VAR B
ON A.MONTH_KEY=B.MONTH_KEY AND A.CUSTOMER_NO = B.CUSTOMER_NO
WHERE A.CUSTOMER_NO = @CUSTOMER AND A.MONTH_KEY = @START_DATE)
IF @EVENT_FLAG = 0 AND @EVENT_12_MONTH_FLAG = 1
BEGIN
UPDATE EVENT_DRV
SET EVENT_DRV.def_flag_final =1
WHERE MONTH_KEY=DATEADD(MONTH,-12,@MONTH_KEY)
BREAK
END
END
FETCH NEXT FROM @EVENT_CURSOR INTO @CUSTOMER;
END
CLOSE @EVENT_CURSOR;
DEALLOCATE @EVENT_CURSOR;
答案 0 :(得分:0)
DECLARE
@EVENT_12_MONTH_FLAG DATETIME
, @CUSTOMER INT
, @EVENT_FLAG INT
, @MONTH_KEY DATETIME
SELECT @EVENT_12_MONTH_FLAG =
CASE
WHEN
(YEAR(A.MONTH_KEY) = YEAR(DEF_MONTH_1) AND MONTH(A.MONTH_KEY) = MONTH(DEF_MONTH_1))
OR
(YEAR(A.MONTH_KEY) = YEAR(WRT_OFF_DTE) AND MONTH(A.MONTH_KEY) = MONTH(WRT_OFF_DTE))
OR
DATEDIFF(MONTH,A.MONTH_KEY,WRT_OFF_DTE) = 1
THEN 1
ELSE 0
END
FROM EVENT_DRV A
JOIN EVENT_VAR B ON A.MONTH_KEY = B.MONTH_KEY AND A.ACCOUNT_NO = B.ACCOUNT_NO
--WHERE -- !!
DECLARE cur CURSOR FAST_FORWARD READ_ONLY LOCAL FOR
SELECT DISTINCT CUSTOMER_NO
FROM dbo.EVENT_DRV
WHERE @EVENT_12_MONTH_FLAG = 1
OPEN cur
FETCH NEXT FROM cur INTO @CUSTOMER
WHILE @@FETCH_STATUS = 0 BEGIN
SELECT @EVENT_FLAG =
CASE
WHEN
DEF_FLAG = 1
OR
DATEDIFF(MONTH, A.MONTH_KEY, WRT_OFF_DTE) = 1
OR
(YEAR(A.MONTH_KEY) = YEAR(WRT_OFF_DTE) AND MONTH(A.MONTH_KEY) = MONTH(WRT_OFF_DTE))
THEN 1
ELSE 0
END
FROM dbo.EVENT_DRV A
JOIN dbo.EVENT_VAR B ON A.MONTH_KEY = B.MONTH_KEY AND A.ACCOUNT_NO = B.ACCOUNT_NO -- !!
WHERE A.CUSTOMER_NO = @CUSTOMER
AND A.MONTH_KEY = DATEADD(MONTH, -12, @MONTH_KEY)
IF @EVENT_FLAG = 0 BEGIN
UPDATE EVENT_DRV
SET EVENT_DRV.def_flag_final = 1
WHERE MONTH_KEY = DATEADD(MONTH, -12, @MONTH_KEY)
AND CUSTOMER_NO = @CUSTOMER -- !!
END
FETCH NEXT FROM cur INTO @CUSTOMER
END
CLOSE cur
DEALLOCATE cur
很难理解您的业务逻辑......无论如何检查此代码