优化T-SQL插入 - temptable,CTE,WHILE循环

时间:2010-11-22 02:53:33

标签: sql sql-server tsql ado.net

我有一种情况需要处理并最终将1000个记录从temptable插入到数据库表中。在每次插入之前,我需要确保满足条件,并且在每次插入之后,我需要更新数据库中的第二个表。我的问题是,目前,运行查询大约需要25分钟,我希望大幅减少时间,以便我的应用程序可以更快地响应。我该怎么办呢?

DECLARE @rowcounter as INTEGER 


                    CREATE TABLE #temporary_phonetable 
                    (
                          rownumber int  not null  identity(1,1), 
                          record_no BIGINT,
                          phone_name BIGINT, 
                          phone_number Varchar(25)  not null  ,
                           responsemessage Varchar(200)  not null  ,
                          messagepriority Varchar(14)  not null  , 
                          phone_id BIGINT, 
                          AD_show  BIGINT, 
                          power_show Varchar(400), 
                          service_provider VARCHAR(30),
                          Phone_flag  VARCHAR(30),
                          questionMessage BIGINT,
                          PRIMARY KEY (phone_id, phone_number, rownumber)
                        ,UNIQUE (questionMessage, record_no, rownumber) 
                    )
                    --GET PHONE DATA 
                                --if phone numbers are sent in from the client, then we want to process those instead 
            IF ( ( ( @listofphones IS NULL OR LEN(@listofphones) <1) AND LEN(@peoplegroups) >0)  )
             BEGIN 
                   --NO PHONENUMBER BUT THERE ARE GROUPS AVAILABLE                        
                              INSERT INTO #temporary_phonetable(phone_name, phone_number, messagepriority, phone_id, AD_show, power_show, responsemessage) 
                              SELECT n.phone_name, n.phone_number,u.messagepriority, n.phone_id , u.AD_show, u.power_show , CASE  @includegreetings   WHEN 1 THEN LTRIM(RTRIM(phone_name)) + @responsemessages 
                                      ELSE @responsemessages END as text_message
                              FROM user u WITH(NOLOCK) 
                              INNER JOIN Phonenumbers n  WITH(NOLOCK) ON n.user_no = u.user_no
                                INNER JOIN PeopleGroupRelations g ON  g.phone_id=n.phone_id  
                                INNER JOIN ( Select items FROM Split(@peoplegroups, @listofphonesdelimiter)) gg ON g.group_no = gg.items 
                              WHERE n.user_no=@userid 
                              AND n.status=''active''
                              SET @rowcounter = @@ROWCOUNT
             END 
             ELSE  IF ( LEN(@listofphones) >1  AND LEN(@peoplegroups) >0)
              BEGIN  
                      --PHONENUMBER AND GROUPS 
                              INSERT INTO #temporary_phonetable(phone_name, phone_number, messagepriority, phone_id, AD_show, power_show, responsemessage) 
                              SELECT n.phone_name, n.phone_number,u.messagepriority, n.phone_id , u.AD_show, u.power_show , CASE  @includegreetings   WHEN 1 THEN LTRIM(RTRIM(phone_name)) + @responsemessages 
                                      ELSE @responsemessages END as text_message
                              FROM  Split(@listofphones, ''|'')  s
                              INNER JOIN PhoneNumbers n  WITH(NOLOCK) ON n.phone_number = s.items
                              INNER JOIN User u WITH(NOLOCK)  ON n.user_no =u.user_no
                              INNER JOIN PeoplegroupRelations g ON  g.phone_id=n.phone_id  
                              INNER JOIN ( Select items FROM Split(@peoplegroups, @listofphonesdelimiter)) gg ON g.group_no = gg.items 
                              WHERE n.user_no=@userid 
                              AND n.status=''active''
                              SET @rowcounter = @@ROWCOUNT
             END 
              ELSE  IF ( LEN(@listofphones) >1  AND LEN(@peoplegroups) >0)
              BEGIN  
                      --PHONENUMBER AND NO GROUPS 
                              INSERT INTO #temporary_phonetable(phone_name, phone_number, messagepriority, phone_id, AD_show, power_show, responsemessage) 
                              SELECT n.phone_name, n.phone_number,u.messagepriority, n.phone_id , u.AD_show, u.power_show , CASE  @includegreetings   WHEN 1 THEN LTRIM(RTRIM(phone_name)) + @responsemessages 
                                      ELSE @responsemessages END as text_message
                              FROM  Split(@listofphones, ''|'')  s
                              INNER JOIN PhoneNumbers n  WITH(NOLOCK) ON n.phone_number = s.items
                              INNER JOIN User u WITH(NOLOCK)  ON n.user_no =u.user_no
                              INNER JOIN PeopleGroupRelations g ON  g.phone_id=n.phone_id  
                              INNER JOIN ( Select items FROM Split(@peoplegroups, @listofphonesdelimiter)) gg ON g.group_no = gg.items 
                              WHERE n.user_no=@userid 
                              AND n.status=''active''
                              SET @rowcounter = @@ROWCOUNT
             END  
             ELSE 
                    BEGIN 
                          -- NO PHONENUMBER NO GROUP --- IE. SEND TO ALL PHONE NUMBERS
                                 INSERT INTO #temporary_phonetable(phone_name, phone_number, messagepriority, phone_id, AD_show, power_show,responsemessage) 
                                SELECT   n.phone_name, n.phone_number,u.messagepriority, n.phone_id , u.AD_show, u.power_show , CASE  @includegreetings   WHEN 1 THEN LTRIM(RTRIM(phone_name)) + @responsemessages 
                                      ELSE @responsemessages END as text_message
                                FROM User u  
                                          INNER JOIN PhoneNumbers n ON n.user_no = u.user_no
                                WHERE
                                        n.status=''active''
                                        AND  n.user_no=@userid 
                                    SET @rowcounter = @@ROWCOUNT 
                    END



                  IF( @rowcounter>0)
                  BEGIN 
                                    DECLARE @service_provider as Varchar(30)
                                    DECLARE @PhoneType as Varchar(30)

                                    IF (LOWER(RTRIM(LTRIM(@sendresponseswhen))) ='now')
                                    BEGIN 
                                                SET @dateresponsessent = GETDATE()
                                     END

                                                      DECLARE @rownumber int
                                                      DECLARE @power_show BIT
                                                      DECLARE  @AD_show BIT 
                                                      set @rownumber = 0 
                                                      WHILE @rownumber < @rowcounter
                                                      BEGIN
                                                                    set @rownumber = @rownumber + 1
                                                                    -- THE VARIABLES 
                                                                                DECLARE @record_no as BIGINT
                                                                                DECLARE @phone_name VARCHAR(30)
                                                                                DECLARE @messagepriority as INTEGER
                                                                                DECLARE @phone_number VARCHAR(30)
                                                                                DECLARE @phone_id BIGINT
                                                                                DECLARE @questionMessage BIGINT

                                                                     SELECT 
                                                                              @phone_name = n.phone_name, @phone_number =n.phone_number, @messagepriority =n.messagepriority, @phone_id=n.phone_id , 
                                                                              @AD_show=n.AD_show, @power_show=n.power_show
                                                                        FROM 
                                                                              #temporary_phonetable n WITH(NOLOCK) 
                                                                        WHERE n.rownumber = @rownumber

                                                                        SET @record_no = AddMessageToQueue(@phone_number, @responsemessages, @dateresponsessent, @savednames, @userid, un.messagepriority, @responsetype, 
                                                                        un.AD_show, un.power_show, @service_provider, @PhoneType)  


                                                                        If(@questionid > 0)
                                                                        BEGIN 
                                                                                SET @questionMessage = AddQuestionMessage(@questionid,@phone_id,  @record_no, DATEADD(d, 30, GETDATE()) )
                                                                        END 


                                                UPDATE #temporary_phonetable SET record_no = @record_no, questionMessage=@questionMessage WHERE phone_number = @phone_number  AND rownumber = @rownumber
                                    END 
                                    IF( @power_show >0)
                                    BEGIN 
                                          SET @responsemessages = @responsemessages + dbo.returnPoweredBy()
                                    END
                                    IF( @AD_show > 0)
                                    BEGIN 
                                          SELECT @responsemessages = @responsemessages + CASE 
                                                                                                            WHEN (LEN(@responsemessages)  + 14)<  160 THEN    dbo.returnAD(@responsemessages) 
                                                                                                            ELSE '''' END 
                                    END


                                    RETURN @rowcounter
                        END

我相信这是大部分问题所在的地方。

WHILE @rownumber&lt; @rowcounter                                                       开始                                                                     设置@rownumber = @rownumber + 1                                                                      - 变量                                                                                 将@record_no声明为BIGINT                                                                                 DECLARE @phone_name VARCHAR(30)                                                                                 将@messagepriority声明为INTEGER                                                                                 DECLARE @phone_number VARCHAR(30)                                                                                 DECLARE @phone_id BIGINT                                                                                 DECLARE @questionMessage BIGINT

                                                                 SELECT 
                                                                          @phone_name = n.phone_name, @phone_number =n.phone_number, @messagepriority =n.messagepriority, @phone_id=n.phone_id , 
                                                                          @AD_show=n.AD_show, @power_show=n.power_show
                                                                    FROM 
                                                                          #temporary_phonetable n WITH(NOLOCK) 
                                                                    WHERE n.rownumber = @rownumber

                                                                    SET @record_no = AddMessageToQueue(@phone_number, @responsemessages, @dateresponsessent, @savednames, @userid, un.messagepriority, @responsetype, 
                                                                    un.AD_show, un.power_show, @service_provider, @PhoneType)  


                                                                    If(@questionid > 0)
                                                                    BEGIN 
                                                                            SET @questionMessage = AddQuestionMessage(@questionid,@phone_id,  @record_no, DATEADD(d, 30, GETDATE()) )
                                                                    END 


                                            UPDATE #temporary_phonetable SET record_no = @record_no, questionMessage=@questionMessage WHERE phone_number = @phone_number  AND rownumber = @rownumber
                                END 

2 个答案:

答案 0 :(得分:0)

在临时表中为rownumber添加唯一约束。将WHILE重写为CTE。使用APPLY调用函数。

答案 1 :(得分:0)

您还可以考虑使用表变量而不是临时表。你不会写入tempdb,因为表变量是在内存中创建的,它们会更快。

This article有一个很好的比较。