写了个存储过程,当合成需要的材料少的时候时间很短,但是十几个的时候,需要5,6秒钟,请高手帮忙优化下ALTER PROCEDURE [dbo].[Usp_Prize_Mixture_Result] --卡片合成结果
@ID INT, --ID
@Code INT, --编码
@Type   INT --类型(25,50,75,100)
AS
BEGIN

--检测VIP会员
DECLARE @VIP INT 
SELECT @VIP = F_VIP FROM T_Prize_Mixture WHERE K_Code = @Code
IF @VIP = 1
BEGIN
IF NOT EXISTS(SELECT * FROM T_User_VIP WHERE K_ID=@ID)
BEGIN
SELECT 2
RETURN
END
END

DECLARE @PropCode int
DECLARE @Num int
DECLARE @Money1 int
DECLARE @Money2 int
DECLARE @Money3 int
DECLARE @Money4 int SELECT @PropCode = F_Code, @Num = F_Num,@Money1 = F_Money1,
@Money2 = F_Money2,@Money3 = F_Money3,@Money4 = F_Money4

FROM T_Prize_Mixture WHERE K_Code = @Code

DECLARE @Money int
IF @Type = 25
BEGIN
set @Money = @Money1
END

IF @Type = 50
BEGIN
set @Money = @Money2
END

IF @Type = 75
BEGIN
set @Money = @Money3
END

IF @Type = 100
BEGIN
set @Money = @Money4
END

BEGIN TRAN Tran_MixturePrize
--检测钱
DECLARE @sign0 INT
EXECUTE [Usp_User_UpdateYMoney_Public] @ID,@Money,0,@sign0 out
IF @sign0 = 0 
BEGIN
ROLLBACK TRAN Tran_MixturePrize
SELECT 4
RETURN
END

--检测特殊道具
DECLARE @Sign INT
EXECUTE [Usp_Prize_Mixture_Check] @ID,@PropCode,@Num,@Sign out
IF @Sign = 2 
BEGIN
ROLLBACK TRAN Tran_MixturePrize
SELECT 3
RETURN
END

--逐一检测合成材料是否足够

IF @Code = 13305 --生日卡(1986/12/30)--11501[0]--12302[2]--12309[9]--12314[A/1]
BEGIN
ROLLBACK TRAN Tran_MixturePrize
SELECT 5
RETURN
END
ELSE
BEGIN
DECLARE @MixCode1 int
DECLARE @MixNum1 int
DECLARE @MixCode2 int
DECLARE @MixNum2 int
DECLARE @MixCode3 int
DECLARE @MixNum3 int
DECLARE @MixCode4 int
DECLARE @MixNum4 int
DECLARE @MixCode5 int
DECLARE @MixNum5 int
DECLARE @MixCode6 int
DECLARE @MixNum6 int
DECLARE @MixCode7 int
DECLARE @MixNum7 int
DECLARE @MixCode8 int
DECLARE @MixNum8 int
DECLARE @MixCode9 int
DECLARE @MixNum9 int
DECLARE @MixCode10 int
DECLARE @MixNum10 int
DECLARE @MixCode11 int
DECLARE @MixNum11 int
DECLARE @MixCode12 int
DECLARE @MixNum12 int
DECLARE @MixCode13 int
DECLARE @MixNum13 int SELECT @MixCode1=F_Code1,@MixNum1=F_Num1,@MixCode2=F_Code2,@MixNum2=F_Num2,
@MixCode3=F_Code3,@MixNum3=F_Num3,@MixCode4=F_Code4,@MixNum4=F_Num4,
@MixCode5=F_Code5,@MixNum5=F_Num5,@MixCode6=F_Code6,@MixNum6=F_Num6,
@MixCode7=F_Code7,@MixNum7=F_Num7,@MixCode8=F_Code8,@MixNum8=F_Num8,
@MixCode9=F_Code9,@MixNum9=F_Num9,@MixCode10=F_Code10,@MixNum10=F_Num10,
@MixCode11=F_Code11,@MixNum11=F_Num11,@MixCode12=F_Code12,@MixNum12=F_Num12,
@MixCode13=F_Code13,@MixNum13=F_Num13 FROM T_Prize_Mixture WHERE K_Code = @Code

DECLARE @Sign1 INT
DECLARE @Sign2 INT
DECLARE @Sign3 INT
DECLARE @Sign4 INT
DECLARE @Sign5 INT
DECLARE @Sign6 INT
DECLARE @Sign7 INT
DECLARE @Sign8 INT
DECLARE @Sign9 INT
DECLARE @Sign10 INT
DECLARE @Sign11 INT
DECLARE @Sign12 INT
DECLARE @Sign13 INT

EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode1,@MixNum1,@Sign1 out
EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode2,@MixNum2,@Sign2 out
EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode3,@MixNum3,@Sign3 out
EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode4,@MixNum4,@Sign4 out
EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode5,@MixNum5,@Sign5 out
EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode6,@MixNum6,@Sign6 out
EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode7,@MixNum7,@Sign7 out
EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode8,@MixNum8,@Sign8 out
EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode9,@MixNum9,@Sign9 out
EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode10,@MixNum10,@Sign10 out
EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode11,@MixNum11,@Sign11 out
EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode12,@MixNum12,@Sign12 out
EXECUTE [Usp_Prize_Mixture_Check] @ID,@MixCode13,@MixNum13,@Sign13 out

IF @Sign1 = 2 OR @Sign2 = 2 OR @Sign3 = 2 OR @Sign4 = 2 OR @Sign5 = 2
OR @Sign6 = 2 OR @Sign7 = 2 OR @Sign8 = 2 OR @Sign9 = 2 OR @Sign10 = 2
OR @Sign11 = 2 OR @Sign12 = 2 OR @Sign13 = 2
BEGIN
ROLLBACK TRAN Tran_MixturePrize
SELECT 5
RETURN
END
END

IF NOT EXISTS(SELECT * FROM T_Prize_UserTicket WHERE F_ID = @ID AND F_Code = @Code)
BEGIN
INSERT T_Prize_UserTicket(F_ID,F_Code,F_Quantity,F_Point)
VALUES(@ID,@Code,1,0)
END
ELSE
BEGIN
SET NOCOUNT ON
UPDATE T_Prize_UserTicket
   SET F_Quantity = F_Quantity + 1
 WHERE F_ID = @ID
   AND F_Code = @Code
SET NOCOUNT OFF
END

COMMIT TRAN Tran_MixturePrize
SELECT 1
END附:存储过程[Usp_Prize_Mixture_Check]
ALTER PROCEDURE [dbo].[Usp_Prize_Mixture_Check]     
@F_ID INT,         --玩家ID
@Code INT,          --奖券编码
@Num        INT,            --数量
@Output     INT OUTPUT      --标志(0失败 1成功)
AS 
BEGIN
SET @Output=0

IF @Code <= 0 OR @Num <= 0 
BEGIN
SET @Output=0
RETURN
END DECLARE @Quantity INT
SET @Quantity = 0

SELECT @Quantity=ISNULL(F_Quantity,0) FROM T_Prize_UserTicket
 WHERE F_ID = @F_ID
                       AND F_Code = @Code
IF (@Quantity < @Num)
BEGIN
SET @Output=2
RETURN
END
ELSE
BEGIN
SET NOCOUNT ON
UPDATE T_Prize_UserTicket
   SET F_Quantity = F_Quantity - @Num
 WHERE F_ID = @F_ID
   AND F_Code = @Code
SET NOCOUNT OFF

SET @Output=1
END
END
--执行后返回:0失败 1成功 2数量不足

解决方案 »

  1.   

    存储过程虽然有可以优化的地方,但是应该来说对于性能没有多大影响。
    这个情况的话可以在表格设计的上找找原因。你的多个select执行速度如何?感觉问题出在这上面,都建立了index了?
      

  2.   

    你可以执行你的存储贵过程,然后用F10进行debug,感觉一下哪步比较慢,然后再来问问题。
    现在这样的代码还是比较长,不好说问题出在那里。
      

  3.   

    首先,你的判断次数过多,尝试把IF/ELSE改成case when 吧。
    其次,[Usp_User_UpdateYMoney_Public]、[Usp_Prize_Mixture_Check]这两个存储过程执行后,是否应该先把select放到rollback前面?我觉得先rollback会不会不执行select?没试过,不好说。你自己试一下吧。
    最后,我个人感觉就是,你的程序性能问题不大,除非索引没用上,不然速度应该不慢,但是判断和返回还是过多,看看有没有改进的方法。