2010-11-22 9 views
0

Ich habe eine Situation, in der ich Tausende von Datensätzen von einem Versuchbar in eine Datenbanktabelle verarbeiten und schließlich einfügen muss. Vor jeder Einfügung muss ich sicherstellen, dass die Bedingungen erfüllt sind und direkt nach jeder Einfügung muss ich eine zweite Tabelle in meiner Datenbank aktualisieren. Mein Problem ist, dass es derzeit etwa 25 Minuten dauert, um die Abfrage auszuführen, und ich möchte diese Zeit drastisch reduzieren, damit meine Anwendung reaktionsfähiger wird. Wie kann ich das bitte tun?Optimieren von T-SQL Einfügen - testable, CTEs, WHILE-Schleifen

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 [email protected] 
           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 [email protected] 
           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 [email protected] 
           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 [email protected] 
            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, [email protected] 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 

Ich glaube, das ist der Ort, an dem der Großteil des Problems liegt.

WHILE @rownumber < @rowcounter set @rownumber BEGIN = @rownumber + 1 - die Variablen DEKLARIEREN @record_no als BIGINT DECLARE- @phone_name VARCHAR (30) DECLARE- @messagepriority als INTEGER DECLARE- @phone_number VARCHAR (30) DECLARE @phone_id BIGINT DEKLARIEREN @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, [email protected] WHERE phone_number = @phone_number AND rownumber = @rownumber 
           END 
+0

Legen Sie fest, was in Ihrem (langen) geposteten Code die Verlangsamung verursacht, und wir könnten Ihnen vielleicht helfen. –

+0

Die Verlangsamung beginnt beim WHILE LOOP. Genau davor läuft der Code ungefähr 0,16 Sekunden. Sobald es die While-Schleife erreicht, erhöht sich die Verarbeitungszeit um 25 Minuten. – Kobojunkie

Antwort

0

Fügen Sie eine eindeutige Integritätsbedingung zu rownumber in Ihrer temporären Tabelle hinzu. Schreibe die WHILE als CTE. Verwenden Sie APPLY, um die Funktionen aufzurufen.

+0

Zählt das nicht? UNIQUE (questionMessage, record_no, rownumber). Oder meinst du das nicht? – Kobojunkie

+0

Nicht wirklich. Du willst das wirklich schnell machen: WHERE n.rownumber = @rownumber. Eine eindeutige Einschränkung oder ein eindeutiger Index für dieses Feld kann Wunder bewirken. Es braucht wirklich Leistung weiter mit der Schleife loszuwerden. –

+0

Auch hinzufügen möchten, dass AddMessageToQueue und AddQuestionQueue sind STOREDPROCS und nicht Funktionen. – Kobojunkie

0

Sie sollten auch eine Tabellenvariable anstelle einer temporären Tabelle verwenden. Sie werden nicht in die Tempdb schreiben, und wenn Tabellenvariablen im Speicher erstellt werden, sind sie schneller.

This article hat einen schönen Vergleich.

+0

Ich habe das versucht, aber nicht viel Unterschied noch. Irgendwelche anderen Vorschläge bitte? – Kobojunkie

+0

Anstatt eine while-Schleife Zeile für Zeile gegen die Tabellenvariable zu prüfen, könnten Sie INSERT..SELECT in die Datenbank einfügen, in der die Bedingungen erfüllt sind. Wenn Sie auch wissen möchten, welche Zeilen die Kriterien nicht erfüllen, können Sie die Bedingungen umkehren, um das herauszufinden. – RLT

+0

Wenn Sie die Abfrage-Schleife betrachten, muss ich tatsächlich eine gespeicherte Prozedur für jede Zeile ausführen, deshalb habe ich die Schleife. Ich weiß, dass ich das nicht für jede Zeile mit INSERT ausführen kann. . . .SELECT, oder kann ich? – Kobojunkie