• 提升存储过程的效率,用减少表的更新次数来实现


    以下存储过程是鄙人前几日发问的那个在线招聘考试系统上用到的存储过程之一,且看该存储过程的书写:

     1/*
     2---------------------------------------------------------------------------------
     3--存储过程名:pro_stuAnswerTime
     4--输入参数:
     5  --@RecruID 招聘ID
     6  --@TestID  考试ID
     7  --@PaperID 试卷ID
     8  --@StuID   考生ID
     9    @SpentHours 剩余小时,
    10    @SpentMinutes 剩余分钟,
    11    @SpentSeconds 剩余秒
    12--输出参数:
    13  --@IsPassedTime 是否超时
    14------------------
    15------------------
    16--用途:
    17--考生考试用时处理
    18
    19---------------------------------------------------------------------------------
    20*/

    21
    22CREATE PROCEDURE dbo.pro_stuAnswerTime 
    23    @RecruID int,
    24    @TestID int,
    25    @PaperID int,
    26    @StuID int,
    27    @SpentHours int,
    28    @SpentMinutes int,
    29    @SpentSeconds int
    30AS
    31    --更新考生用时表
    32    if (select count(*from Tb_StuTestRecord where  RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID=0
    33        begin 
    34            insert into Tb_StuTestRecord(RecruID,TestID,PaperID,StuID,SpentHours,SpentMinutes,SpentSeconds) values(@RecruID,@TestID,@PaperID,@StuID,@SpentHours,@SpentMinutes,@SpentSeconds)
    35        end
    36    else
    37        begin
    38            update Tb_StuTestRecord set SpentHours=SpentHours+@SpentHours,SpentMinutes=SpentMinutes+@SpentMinutes,SpentSeconds=SpentSeconds+@SpentSeconds 
    39            where RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID;
    40            
    41            
    42            
    43        --以下代码用来进行 分 秒 的转换
    44        --即60秒 换做一分,60分换做一秒
    45         declare @min int;
    46         declare @seconds int;
    47         
    48         --从表中查出相应的秒来判断
    49         select @seconds=SpentSeconds from Tb_StuTestRecord
    50         where  RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID
    51         
    52         --秒大于60
    53         if @seconds>=60 
    54            begin
    55                    update Tb_StuTestRecord set SpentMinutes=SpentMinutes+1,SpentSeconds=0
    56                where RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID;
    57            end
    58        
    59         --从表中查出相应的分来判断
    60         select @min=SpentMinutes from Tb_StuTestRecord
    61         where  RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID
    62         --分钟大于60
    63         if @min>=60
    64            begin 
    65                update Tb_StuTestRecord set SpentHours=SpentHours + 1,SpentMinutes=0 where RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID;
    66            end
    67        
    68    end
    69

    且看一下该存储过程对数据表访问了几次:
    1.第32行,先从表中查出了一条记录,查询一次
    2.如果走分支一的话,则只对表进行一次更新
    3.如果走分支二,则会出现如下情况:
        3.1 更新一次表
        3.2 如果秒大于60,则又更新一次表
        3.3 如果分大于60,则第三次更新表

    综上,对数据表的访问的最大次数可能达到1+1+1+1=4次,其中一次查询、三次更新,那么这样的效率肯定是比较低的。

    针对以上存储过程,采取了网友们的建议,对以上存储过程进行了如下优化:
     1
     2declare @hour int;
     3declare @min int;
     4declare @sec int;
     5declare @affectedrowscount int;--表示是否更新的学生考试表(如果其值为0,则说明应该向该表中插入记录)
     6
     7--从表中查出考生已用时、分、秒
     8select @hour=SpentHours,@min=SpentMinutes,@sec=SpentSeconds from Tb_StuTestRecord
     9         where  RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID
    10        
    11        --声明更新之后应该是的时分秒
    12        declare @okhour int;
    13        declare @okmin int;
    14        declare @oksec int;
    15        
    16        set @okhour=@hour+@SpentHours;
    17        set @okmin = @min + @SpentMinutes;
    18        set @oksec= @sec + @SpentSeconds;
    19
    20    if @oksec>=60
    21    begin 
    22        set @okmin = @okmin +1;
    23        set @oksec = @oksec -60;
    24    end
    25
    26    if @okmin>=60
    27    begin
    28        set @okhour = @okhour +1;
    29        set @okmin = @okmin  - 60;
    30    end
    31    
    32        update Tb_StuTestRecord set SpentHours=@okhour,SpentMinutes=@okmin,SpentSeconds=@oksec where RecruID=@RecruID and TestID=@TestID and PaperID=@PaperID and StuID=@StuID;
    33        
    34        --取出受影响的行数,作为下面的一个判断条件
    35         set @affectedrowscount = @@rowcount;
    36
    37--如果更新时影响的行数为0,则说明表中并无该记录,此时应
    38    if(@affectedrowscount = 0)
    39        begin 
    40                insert into Tb_StuTestRecord(RecruID,TestID,PaperID,StuID,SpentHours,SpentMinutes,SpentSeconds) values(@RecruID,@TestID,@PaperID,@StuID,@SpentHours,@SpentMinutes,@SpentSeconds)
    41        end
    42GO

    且看优化后的存储过程:
    1.第8 行从数据库中查询出相应的记录,并赋值给三个相应的变量
    2.更新一次表
    3.如果更新影响的行数为0,则向数据库中插入记录(此分支在考生答题的整个过程中只可能走一次)

    由此:整个存储过程对该表进行了相当于2次的访问,其中一次查询,一次更新

    比之第一个存储过程,优化之后的存储过程减少了三次的对数据更新的次数。
    对于为什么减少了数据表的更新次数,请大家看存储过程。在此鄙人就不啰嗦了。
    点个广告:
  • 相关阅读:
    Android开发学习笔记-SharedPreferences的用法
    Android开发学习笔记-自定义组合控件
    webpack 4 教程
    react 生命周期图解
    git 操作说明
    echars 3.0 去掉柱状图阴影用什么属性
    react——Table组件
    antd ——按钮
    react——Table组件列中靠左 靠右对齐解决方案
    react中异步的使用
  • 原文地址:https://www.cnblogs.com/hanxianlong/p/939084.html
Copyright © 2020-2023  润新知