无鱼之水

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

今天改一处效率问题,对一个临时表进行分段累加计算,累加方式为累积(Cumulative Aggregations),
大约9万条记录的表,时间超过三分钟。
执行环境:
SQL SERVER 2005 ENTERPRISE EDITION
8 CPU CORES
16G MAXSERVERMEMORY

累加算法如下:

 

代码
BEGIN TRAN
UPDATE #JCCMX SET
[JC] = (
SELECT SUM(MT_0.ZC) AS MT_0_ZC_SUM
FROM #JCCMX AS MT_0
WHERE (MT_0.CLID = #JCCMX.CLID) AND (MT_0.ID <= #JCCMX.ID)
)
ROLLBACK

 

 


    执行计划可以想象,内连接驱动假脱机(Inner Join Drived Eager Spool)。其中假脱机运算符占据了多数的CPU时间。
    一开始打算使用开窗聚合函数(Window Aggregations),查资料发现SQL SERVER 2005只为聚合函数实现了带Partion语句的开窗,不支持Order语句,即:
 

SELECT SUM(ZC) OVER (PARTITION BY CLID)

 

 

不支持:
 

SELECT SUM(ZC) OVER (PARTITION BY CLID ORDER BY ID)

 

 

无奈放弃。
使用游标算法,时间稍好,90s,但是也难接受。 

代码
BEGIN TRAN
CREATE INDEX IDX ON #JCCMX(ID, CLID) INCLUDE(JC, ZC)
DECLARE @ID INT
DECLARE @OID INT
DECLARE @NID INT
DECLARE @RN INT
DECLARE @ZC FLOAT
DECLARE @SUM FLOAT

DECLARE CUR CURSOR FOR SELECT CLID, ZC, ID FROM #JCCMX
OPEN CUR
FETCH NEXT FROM CUR INTO @NID, @ZC, @ID
WHILE @@FETCH_STATUS = 0
BEGIN
IF @OID = @NID
SET @SUM = @SUM + @ZC
ELSE
SET @SUM = @ZC

UPDATE #JCCMX
SET JC = @SUM
WHERE ID = @ID;

SET @OID = @NID
FETCH NEXT FROM CUR INTO @NID, @ZC, @ID
END
CLOSE CUR
DEALLOCATE CUR
ROLLBACK

 

 

    于是放弃对SQL SERVER的幻想,将上述游标代码使用DELPHI实现,使用AppServer计算JC列。

    开发机(Core 2/2G),9万条记录,1s以内计算完毕。

posted on 2010-12-29 18:43  陈伟强  阅读(231)  评论(0编辑  收藏  举报