none
Umstellung Cursor von MS SQL Server 2005 auf MS SQL Server 2008 RRS feed

  • Frage

  • Hallo Zusammen,

    im Rahmen einer Datenbankmigration habe ich das Problem, dass in einem Job Tabellen gefüllt werden sollen (mit Hilfe eines Cursors)- siehe Code Beispiel vom MS SQL Servers 2005 auf den MS SQL Server 2008. dieser Job läuft auf dem alten System max. 20 min. Nach Übernahme auf den neuen Server dauert er länger als 7 Stunden.

    Weiß hier jemand, woran das liegen kann ?

    Beste Grüße

    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[#CR_OSW_Involvement_Insert]') AND type in (N'U'))
    DROP TABLE [dbo].[#CR_OSW_Involvement_Insert]
     
    CREATE TABLE [dbo].[#CR_OSW_Involvement_Insert]
    (
      CR_Number VARCHAR(11),
      CR_Subnumber VARCHAR(4),
    )
    
     
    INSERT INTO [dbo].[#CR_OSW_Involvement_Insert]
               ([CR_Number],[CR_Subnumber])
     
      select CR_I_CR_Number, CR_I_Subnumber from IFU.V_tbl_CR 
      where CR_I_CR_Number+CR_I_Subnumber NOT IN 
      (
      SELECT DISTINCT CR_Number+CR_Subnumber  from  [OSW].[tbl_CR_Involvement_Analysis]
      ) 
     
    DECLARE @n Int -- Org_ID
     
    set @n = 0
     
    WHILE @n < 54 -- zur Zeit Org_ID  1 bis 53
    BEGIN   
      set @n = @n + 1
      -- print @n
      INSERT INTO [OSW].[tbl_CR_Involvement_Analysis]
               ([active]
               ,[CR_Number]
               ,[CR_Subnumber]
               ,[Org_ID]
               ,[Ins_Date]
               ,[Ins_User])
      select DISTINCT 1, CR_Number, CR_Subnumber, @n, GETDATE(), 'Script' 
      from [dbo].[#CR_OSW_Involvement_Insert]
    END 
    
    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[#CR_OSW_Involvement_Insert]') AND type in (N'U'))
    DROP TABLE [dbo].[#CR_OSW_Involvement_Insert]
    
    
    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[#MP_OSW_Involvement_Insert]') AND type in (N'U'))
    DROP TABLE [dbo].[#MP_OSW_Involvement_Insert]
     
    CREATE TABLE [dbo].[#MP_OSW_Involvement_Insert]
    (
      MP_Number VARCHAR(6)
    )
     
    INSERT INTO [dbo].[#MP_OSW_Involvement_Insert]
               ([MP_Number])
     
      select MP_I_MP_Number from IFU.V_tbl_MP 
      where MP_I_MP_Number NOT IN 
      (
      SELECT DISTINCT MP_Number  from  [OSW].[tbl_MP_Involvement_Analysis]
      ) 
     
    -- DECLARE @n Int -- Org_ID
     
    set @n = 0
     
    WHILE @n < 54 -- zur Zeit Org_ID  1 bis 53
    BEGIN   
      set @n = @n + 1
      -- print @n
      INSERT INTO [OSW].[tbl_MP_Involvement_Analysis]
               ([active]
               ,[MP_Number]
               ,[Org_ID]
               ,[Ins_Date]
               ,[Ins_User])
      select DISTINCT 1, MP_Number, @n, GETDATE(), 'Script' 
      from [dbo].[#MP_OSW_Involvement_Insert]
    END 
    
    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[#MP_OSW_Involvement_Insert]') AND type in (N'U'))
    DROP TABLE [dbo].[#MP_OSW_Involvement_Insert]

    Freitag, 20. Oktober 2017 09:14

Antworten

  • Hallo!

    Ich sehe hier keinen Cursor, sondern nur eine Schleife. Diese würde ich streichen und durch einen Cross Join mit einer Number-Tabelle ersetzen, die Du auch rekursiv bereitstellen kannst. (Falls ich die Logik richtig verstanden habe!)

    -- Demo für rekursive CTE
    With Numbers (n) as
    (Select 1 as n 
    UNION ALL
    Select n+1 
    from Numbers
    where n <= 52)
    Select n
    from Numbers
    ;
    
    -- INSERT into ...
    With Numbers (n) as
    (Select 1 as n 
    UNION ALL
    Select n+1 
    from Numbers
    where n <= 52)
    select DISTINCT 1, CR_Number, CR_Subnumber, Numbers.n, GETDATE(), 'Script' 
    from [dbo].[#CR_OSW_Involvement_Insert],
    Numbers 
    ;

    Ansonsten muss man die Ausführungspläne anschauen oder vergleichen, wenn man herausfinden will, was jetzt so lange dauert!

    Hast Du passende Indizes für Deine Where-Bedingungen?

    Eine abschließende Anmerkung: SQL Server 2008 ist auch nicht gerade aktuell. Was hindert Dich direkt eine aktuelle Version (2017) zu nehmen?


    Einen schönen Tag noch, Christoph -- Data Platform MVP - http://www.insidesql.org/blogs/cmu


    Freitag, 20. Oktober 2017 11:57

Alle Antworten

  • Hallo!

    Ich sehe hier keinen Cursor, sondern nur eine Schleife. Diese würde ich streichen und durch einen Cross Join mit einer Number-Tabelle ersetzen, die Du auch rekursiv bereitstellen kannst. (Falls ich die Logik richtig verstanden habe!)

    -- Demo für rekursive CTE
    With Numbers (n) as
    (Select 1 as n 
    UNION ALL
    Select n+1 
    from Numbers
    where n <= 52)
    Select n
    from Numbers
    ;
    
    -- INSERT into ...
    With Numbers (n) as
    (Select 1 as n 
    UNION ALL
    Select n+1 
    from Numbers
    where n <= 52)
    select DISTINCT 1, CR_Number, CR_Subnumber, Numbers.n, GETDATE(), 'Script' 
    from [dbo].[#CR_OSW_Involvement_Insert],
    Numbers 
    ;

    Ansonsten muss man die Ausführungspläne anschauen oder vergleichen, wenn man herausfinden will, was jetzt so lange dauert!

    Hast Du passende Indizes für Deine Where-Bedingungen?

    Eine abschließende Anmerkung: SQL Server 2008 ist auch nicht gerade aktuell. Was hindert Dich direkt eine aktuelle Version (2017) zu nehmen?


    Einen schönen Tag noch, Christoph -- Data Platform MVP - http://www.insidesql.org/blogs/cmu


    Freitag, 20. Oktober 2017 11:57
  • Hallo Christoph,

    vielen Dank für Dein Feedback. Leider hatte ich den falschen Code gepostet. Der richtige Problemfall ist dieser hier.... es hat sich definitiv nichts an de Tabellen geändert. Ich versteh einfach nicht, warum es jetzt anstatt 1 h 13 Stunden dauert.

    Bin für jeden Rat dankbar!

    Beste Grüße

    Claudia

    DECLARE @V_CR_Number char(11);
    
    DECLARE @V_CR_Subnumber char(4);
    
    DECLARE @V_Count int;
    
    DECLARE @V_n Int -- Org_ID
    
     
    
    -- CR
    
    DELETE [OSW].[tbl_CR_Involvement_Analysis_Test]
    
     
    
     
    
    set @V_n = 0
    
     
    
    DECLARE curCR_OSW_Involvement CURSOR
    
    FORWARD_ONLY
    
    FORselect CR_Number, CR_Subnumber from DWH.tbl_CR ORDER BY CR_Number, CR_Subnumber;
    
     
    
    OPEN curCR_OSW_Involvement;
    
    FETCH NEXT FROM curCR_OSW_Involvement
    
    INTO @V_CR_Number, @V_CR_Subnumber;
    
    WHILE@@FETCH_STATUS = 0
    
    BEGIN
    
      set @V_n = 0
    
     
    
      WHILE @V_n < 120 -- zur Zeit Org_ID  1 bis 53
    
      BEGIN  
    
        set @V_n = @V_n + 1;
    
     
    
        SELECT @V_Count = COUNT(*) FROM [OSW].[tbl_CR_Involvement_Analysis] WHERE
    
                      [CR_Number] = @V_CR_Number AND [CR_Subnumber] = @V_CR_Subnumber
    
                      AND [Org_ID] = @V_n;
    
        IF @V_Count = 0
    
        BEGIN
    
          INSERT INTO [OSW].[tbl_CR_Involvement_Analysis_Test]
    
                   ([active]
    
                   ,[CR_Number]
    
                   ,[CR_Subnumber]
    
                   ,[Org_ID]
    
                   ,[Ins_Date]
    
                   ,[Ins_User])
    
          VALUES(1, @V_CR_Number, @V_CR_Subnumber, @V_n, GETDATE(), 'Script')
    
        END
    
      END
    
     
    
      FETCH NEXT FROM curCR_OSW_Involvement
    
      INTO @V_CR_Number, @V_CR_Subnumber;
    
    END;
    
    DEALLOCATE curCR_OSW_Involvement;
    
    
    

    Montag, 23. Oktober 2017 14:47