Sql存储过程需要花费大量时间来执行

时间:2015-01-30 07:30:54

标签: sql sql-server stored-procedures

我面临一个大问题,下面的存储过程需要花费大量时间来执行。请帮我找到以下存储过程的问题。

我们需要将excel中的批量订阅者列表插入到数据库中。但是只有60个订阅者在一分钟内插入到db中。

请帮我解决这个问题。

 USE [SMS]
    GO
    /****** Object:  StoredProcedure [dbo].[SP_ProcessFile]    Script Date: 01/30/2015 12:56:59 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO



    ALTER PROCEDURE [dbo].[SP_ProcessFile] 


        @JobCode varchar(25)
        WITH RECOMPILE
    AS
    declare
    @jobCode1 Varchar(50),
    @count int,@Code varchar(50),@Name [varchar](50),@Date Datetime,@Status int,
    @i int,@EUCount int,@SubCount int,
    @Add1 nvarchar(3000) ,
    @Add2 nvarchar(500) ,
    @Add3 nvarchar(500) 
    ,@refdate  [varchar](50) ,
    @reference  [varchar](50) ,
        @Joined [varchar](50),
        @Joinmonth [nvarchar](50),
        @Activated [varchar](50),
        @ActivMonth [nvarchar](50),
        @Center [varchar](50) ,
        @Region [varchar](50) ,
        @Area [varchar](50) ,
        @Modem [varchar](50) ,
        @Adomstatus [varchar](50)
    ,   @AddCode [varchar](50)
    set @i = 1
        Set @jobCode1 =@JobCode
    BEGIN
        SET NOCOUNT ON

        Set @Status =    (Select Distinct(status) from TSMST1005 where Jobcode = @jobCode1)

    if (@Status = 0)
        begin
            Select '1' as res
        end
        else
        begin

        CREATE TABLE #tblSMS(pID int identity(1,1),     
        [Reference] [nvarchar](50) NULL,
        [Date] [varchar](50) NOT NULL,
        [Code] [nvarchar](50) NULL,
        [Subname] [varchar](500) NULL,
        [Address1] [nvarchar](3000) NULL,
        [Address2] [nvarchar](500) NULL,
        [Address3] [nvarchar](500) NULL,
        [Joined] [varchar](50) NULL,
        [Joinmonth] [varchar](50) NULL,
        [Activated] [varchar](50) NULL,
        [ActivMonth] [nvarchar](50) NULL,
        [Center] [varchar](50) NULL,
        [Region] [varchar](50) NULL,
        [Area] [varchar](50) NULL,
        [Modem] [varchar](50) NULL,
        [Adomstatus] [varchar](50) NULL,
        [RefDate] [varchar](50) NOT NULL)
        insert into #tblSMS

        SELECT  Reference,[Date],
        Code,Subname ,Address1 ,Address2 ,Address3 ,
        Joined  , Joinmonth ,Activated, ActivMonth ,
        Center,Region,Area,Modem,Adomstatus ,refdate   FROM TSMST1005 where jobcode = @jobCode1 and Status =1

        WHILE @i <= (SELECT COUNT(*) FROM #tblSMS)
            BEGIN
            SELECT 
        @Code =Code,
        @Name = Subname,
        @Date =[Date],
    @Add1 =Address1 ,
    @Add2 =Address2 ,
    @Add3= Address3,

    @reference  =Reference ,
        @Joined = Joined,
        @Joinmonth =Joinmonth,
        @Activated =Activated,
        @ActivMonth =ActivMonth,
        @Center = Center,
        @Region = Region,
        @Area= Area,
        @Modem = Modem ,
        @Adomstatus =Adomstatus,
    @refdate = RefDate 

            From #tblSMS where pID = @i 

        Insert into TCMST5001 (CompanyCode  , Address1,Address2 ,Address3 ,CreatedDate ,Status) values('001',@Add1 ,@Add2,@Add3,GETDATE(),1)
        Set @count = SCOPE_IDENTITY()

        Set @AddCode = 'ADD' + Cast(@count As Varchar(10))


        Update TCMST5001 Set Code =@AddCode Where AddressID =@count 
        Set @EUCount = (Select COUNT(*) from TCCOM0005 where EnterpriseUnitCode = @Center)
        if (@EUCount = 0)
        Begin
        Insert into TCCOM0005(AddressCode,CompanyCode,EnterpriseUnitCode,EnterpriseUnitName,Status) values(@count ,'001',@Center,@Center ,1)
        END
      Set @SubCount = (Select COUNT(*) from TSMST1001 where Subscriber = @Code) 
      if (@SubCount  =0)
      begin
      Insert into TSMST1001(ActivationDate ,refdate , Address ,AlternateName ,Area ,Region ,Subscriber,Name ,date ,CreatedDate ,EnterpriseUnit ,Status) 

      values(@Activated,@refdate ,@count ,@Name,@Area,@Region,@Code,@Name ,@Joined ,GETDATE(),@Center,@Adomstatus)
      end
      Insert into TSMST1003 (Device ,CreatedDate ,Subscriber,StartDate) values 


(@Modem,GETDATE(),@Code,@Activated)

            SET @i = @i + 1
            Update TSMST1005 Set Status = 0 where Jobcode = @jobCode1 
            Select '3' as res
        END
        END
        Drop table #tblSMS 
        end

2 个答案:

答案 0 :(得分:0)

很难给你100%的工作程序。但是,您的问题是您要逐行插入记录。而不是这样做,你需要在BULK中插入记录。那会更快。有重写程序。您仍然需要通过相同的逻辑重写2个插入。当然可能存在缺陷,因为它完全未经测试。无论如何,我们在这里:

    USE [SMS]
    GO
    /****** Object:  StoredProcedure [dbo].[SP_ProcessFile]    Script Date: 01/30/2015 12:56:59 ******/
SET ANSI_NULLS ON
    GO
SET QUOTED_IDENTIFIER ON
    GO



ALTER PROCEDURE [dbo].[SP_ProcessFile] @JobCode VARCHAR(25)
    WITH RECOMPILE
AS

    BEGIN
        SET NOCOUNT ON

        SET @Status = ( SELECT TOP 1 status 
                        FROM    TSMST1005
                        WHERE   Jobcode = @jobCode
                      )

        IF ( @Status = 0 )
            BEGIN
                SELECT  '1' AS res
            END
        ELSE
            BEGIN

                CREATE TABLE #tblSMS
                    (
                      pID INT IDENTITY(1, 1) ,
                      [Reference] [NVARCHAR](50) NULL ,
                      [Date] [VARCHAR](50) NOT NULL ,
                      [Code] [NVARCHAR](50) NULL ,
                      [Subname] [VARCHAR](500) NULL ,
                      [Address1] [NVARCHAR](3000) NULL ,
                      [Address2] [NVARCHAR](500) NULL ,
                      [Address3] [NVARCHAR](500) NULL ,
                      [Joined] [VARCHAR](50) NULL ,
                      [Joinmonth] [VARCHAR](50) NULL ,
                      [Activated] [VARCHAR](50) NULL ,
                      [ActivMonth] [NVARCHAR](50) NULL ,
                      [Center] [VARCHAR](50) NULL ,
                      [Region] [VARCHAR](50) NULL ,
                      [Area] [VARCHAR](50) NULL ,
                      [Modem] [VARCHAR](50) NULL ,
                      [Adomstatus] [VARCHAR](50) NULL ,
                      [RefDate] [VARCHAR](50) NOT NULL
                    )
                INSERT  INTO #tblSMS
                        SELECT  Reference ,
                                [Date] ,
                                Code ,
                                Subname ,
                                Address1 ,
                                Address2 ,
                                Address3 ,
                                Joined ,
                                Joinmonth ,
                                Activated ,
                                ActivMonth ,
                                Center ,
                                Region ,
                                Area ,
                                Modem ,
                                Adomstatus ,
                                RefDate
                        FROM    TSMST1005
                        WHERE   jobcode = @jobCode1
                                AND Status = 1

                WHILE @i <= ( SELECT    COUNT(*)
                              FROM      #tblSMS
                            )
                    BEGIN

                        DECLARE @minPK INT;
                        SELECT @minPK = MAX(AddressID ) FROM TCMST5001; -- I believe that it is identity column. If not change it to the proper one
                        INSERT  INTO TCMST5001
                                ( CompanyCode ,
                                  Address1 ,
                                  Address2 ,
                                  Address3 ,
                                  CreatedDate ,
                                  Status
                                )
                       SELECT '001', Address1, Address2, Address3, GETDATE(), 1 FROM #tblSMS;

                        SET @AddCode = 'ADD' + CAST(@count AS VARCHAR(10))


                        UPDATE  TCMST5001
                        SET     Code = 'ADD' + CAST(AddressID AS VARCHAR(10))
                        WHERE   AddressID > @minPK ;

                        INSERT INTO TCCOM0005
                        SELECT ee.cnt, t.center, t.Center, 1
                        FROM #tblSMS t
                        CROSS APPLY ( SELECT COUNT(*) AS cnt FROM  TCCOM0005 e WHERE e.EnterpriseUnitCode = t.Center) ee
                        WHERE ee.cnt > 0

                        -- THE SAME LOGIC MUST BE DONE WITH THESE 2 INSERTS

                       SET @SubCount = ( SELECT    COUNT(*)
                                          FROM      TSMST1001
                                          WHERE     Subscriber = @Code
                                        ) 
                        IF ( @SubCount = 0 )
                            BEGIN
                                INSERT  INTO TSMST1001
                                        ( ActivationDate ,
                                          refdate ,
                                          Address ,
                                          AlternateName ,
                                          Area ,
                                          Region ,
                                          Subscriber ,
                                          Name ,
                                          date ,
                                          CreatedDate ,
                                          EnterpriseUnit ,
                                          Status
                                        )
                                VALUES  ( @Activated ,
                                          @refdate ,
                                          @count ,
                                          @Name ,
                                          @Area ,
                                          @Region ,
                                          @Code ,
                                          @Name ,
                                          @Joined ,
                                          GETDATE() ,
                                          @Center ,
                                          @Adomstatus
                                        )
                            END
                        INSERT  INTO TSMST1003
                                ( Device ,
                                  CreatedDate ,
                                  Subscriber ,
                                  StartDate
                                )
                        VALUES  ( @Modem ,
                                  GETDATE() ,
                                  @Code ,
                                  @Activated
                                )

                        UPDATE  t
                        FROM TSMST1005 t
                         SET     Status = 0
                        JOIN #tblSMS tmp
                          ON tmp.jobCode1 = t.Jobcode

                        SELECT  '3' AS res
                    END
            END
        DROP TABLE #tblSMS 
    END

答案 1 :(得分:0)

一些提示将是。避免在每一步都这样做。

SELECT COUNT(*) FROM #tblSMS

而是将计数值分配给局部变量,并检查i是否相同。

此外,您经常从这些表中选择值(TCCOM0005,TSMST1001,TSMST1003),最好检查这些表是否具有正确的索引。