有一段时间没对Top SQL提出优化建议了,周五开发小伙伴说:"有一个存储过程执行了两个多小时还没完成,我只是把原来具体语句修改为动态拼接语句而已,之前十分钟就好了!"
纳尼?!改过语句!我什么都不知情!
存储过程业务不算复杂,统计各游戏、各代理商前一天的推广用户量、房卡购买金额、房卡消耗量、活跃用户量、新增活跃用户量
其中代理商存在层级关系(1级、2级),1级的数据=1级代理本身+其下面的2级代理数据。由于不同的游戏记录在不同的表格,开发小伙伴将各游戏对应的数据表、统计字段保存到一张配置表
/******** 简化代码、库名|表名已做替换 ********/ DECLARE loop_cursor CURSOR FOR SELECT aui.KindID,aui.KindName,aui.AgentUserID,aui.AgentAccounts,aui.AgentNickName,aui.AgentLevel,aui.HighAccounts,aui.Personal,ais.UserID,ais.NickName FROM LnkServer.DBname.dbo.AgentUserInfo aui WITH(NOLOCK) LEFT JOIN LnkServer.DBname.dbo.AccountsInfoSimple ais WITH(NOLOCK) on aui.HighAccounts = ais.accounts ORDER BY aui.OperateDate DESC OPEN loop_cursor FETCH NEXT FROM loop_cursor INTO @KindID,@KindName,@AgentUserID,@AgentAccounts,@AgentNickName,@AgentLevel,@HighAccounts,@Personal,@HighAgentUserID,@HighAgentNickName WHILE @@FETCH_STATUS = 0 BEGIN declare ... SELECT @GroupStatRecord=ISNULL(GroupStatRecord,'SparrowGroupStatRecord') ,@CardConsumedField=ISNULL(CardConsumedField,'CostRoomCards') FROM DBname.dbo.SparrowConfigForAll WITH(NOLOCK) WHERE KindID=@KindID --推广用户量 --房卡购买金额 --房卡消耗量 DECLARE @sqlVoucherConsumeTotal NVARCHAR(MAX); set @sqlVoucherConsumeTotal='select @VoucherConsumeTotal = isnull(sum('+@CardConsumedField+'),0) from ' +@GroupStatRecord+' with(nolock) where StartDate between @StartTime and @EndTime And KindID=@KindID AND UserID in ( SELECT DISTINCT ais.UserID FROM LnkServer.DBname.dbo.AccountsInfoSimple ais WITH(NOLOCK) INNER JOIN LnkServer.DBname.dbo.AgentBindUser T WITH(NOLOCK) ON ais.UserID = T.UserID WHERE (T.CreateDate <= @EndTime) AND T.KindID = @KindID AND T.AgentAccounts = @AgentAccounts )' DECLARE @pargamVoucherConsumeTotal NVARCHAR(1000) SET @pargamVoucherConsumeTotal = '@VoucherConsumeTotal DECIMAL(18,0) out,@StartTime DATETIME,@EndTime DATETIME,@KindID INT,@AgentAccounts VARCHAR(100) ' exec sp_executesql @sqlVoucherConsumeTotal, @pargamVoucherConsumeTotal, @VoucherConsumeTotal=@VoucherConsumeTotal OUTPUT, @StartTime=@StartTime, @EndTime=@EndTime, @KindID=@KindID, @AgentAccounts=@AgentAccounts --单天、累计活跃用户量 --单天、累计新增活跃用户量 IF(@AgentLevel=1) BEGIN --重复上面的代码,AgentAccounts条件调整 --累加1级代理下的2级代理 --推广用户量 --房卡购买金额 --房卡消耗量 --------------------------- DECLARE @sqlVoucherConsumeTotalTemp NVARCHAR(MAX); set @sqlVoucherConsumeTotalTemp='select @VoucherConsumeTotalTemp =isnull(sum('+@CardConsumedField+'),0) from '+@GroupStatRecord+' with(nolock) where StartDate between @StartTime and @EndTime And KindID=@KindID AND UserID in ( SELECT DISTINCT ais.UserID FROM LnkServer.DBname.dbo.AccountsInfoSimple ais WITH(NOLOCK) INNER JOIN LnkServer.DBname.dbo.AgentBindUser T WITH(NOLOCK) ON ais.UserID = T.UserID WHERE (T.CreateDate <= @EndTime) AND T.KindID = @KindID AND T.AgentAccounts IN (select AgentAccounts from LnkServer.DBname.dbo.AgentUserInfo where HighAccounts = @AgentAccounts) )' DECLARE @pargamVoucherConsumeTotalTemp NVARCHAR(1000) SET @pargamVoucherConsumeTotalTemp = '@VoucherConsumeTotalTemp DECIMAL(18,0) out,@StartTime DATETIME,@EndTime DATETIME,@KindID INT,@AgentAccounts VARCHAR(100)' exec sp_executesql @sqlVoucherConsumeTotalTemp, @pargamVoucherConsumeTotalTemp, @VoucherConsumeTotalTemp=@VoucherConsumeTotalTemp OUTPUT, @StartTime=@StartTime, @EndTime=@EndTime, @KindID=@KindID, @AgentAccounts=@AgentAccounts --单天、累计活跃用户量 --单天、累计新增活跃用户量 END SET @VoucherConsumeTotal = @VoucherConsumeTotal + @VoucherConsumeTotalTemp insert into AgentSpreadDayStatistics... FETCH NEXT FROM loop_cursor INTO @KindID,@KindName,@AgentUserID,@AgentAccounts,@AgentNickName,@AgentLevel,@HighAccounts,@Personal,@HighAgentUserID,@HighAgentNickName END CLOSE loop_cursor DEALLOCATE loop_cursor