Announcement

Collapse
No announcement yet.

Performanceproblem bei Insert

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Performanceproblem bei Insert

    Hallo,
    ich habe ein Stored Procedure, welche folgende Aufgaben erledigt:
    1. Durchlaufen einer Stammdatentabelle mittels Cursor und weitergabe der jeweiligen Teilenummer
    2. Die CTE (stl) durchläuft eine mehrstufige Stückliste und ermittelt dabei die maximale Beschaffzeit (be_zeit) eines Teiles für die jeweilige Stufe
    3. Die ermittelten Daten der CTE (stl) werden in einer Tabelle abgespeichert. Hierbei ermittelt die Case-Abfrage noch,ob es sich beim jeweiligen Teil um einen Knoten für die nächste Stufe handelt

    Das alles funktioniert wunderbar, nur es dauert zu lange (viel zu lange). Für ca. 44.000 eingefügte Datensätze benötigt es ca. 2h25min.
    Hier nun meine Stored Procedure
    Code:
    Declare @BAUKASTENNR nvarchar(12);
    
    declare cur cursor for
    SELECT Distinct TEILENR FROM TA_TEILE
    
    open cur
    
    fetch next from cur into @BAUKASTENNR
    while @@fetch_status = 0
    
    BEGIN
    with stl as 
    	(Select 
    		cast(TEILENR as nvarchar(12)) as BG,
    		cast(TEILENR as nvarchar(12)) as baukastennr,
    		cast(TEILENR as nvarchar(12)) as einzelteilnr,
    		cast((BE_ZEIT_1 + BE_ZEIT_2) as numeric(5,0)) as beschaffzeit,
    		cast(BE_ZEIT_1 as numeric(5,0)) as BZ_1,
    		cast(BE_ZEIT_2 as numeric(5,0)) as BZ_2,
    		cast(BE_ZEIT_3 as numeric(5,0)) as BZ_3,
    		0 as level
    	from TA_DISPO
    	where TEILENR = @BAUKASTENNR
    union all
    
    select
    	@BAUKASTENNR as BG
    	,A.baukastennr
    	,A.einzelteilnr
        	,cast(max(B.BE_ZEIT_1 + B.BE_ZEIT_2)
    		over (PARTITION by A.BAUKASTENNR) as numeric(5,0)) AS be_zeit
    	,cast(B.BE_ZEIT_1 as numeric(5,0)) as BZ_1
    	,cast(B.BE_ZEIT_2 as numeric(5,0)) as BZ_2
    	,cast(B.BE_ZEIT_3 as numeric(5,0)) as BZ_3
    	,level +1
    from
      TA_STÜCKLISTE as A INNER JOIN TA_DISPO as B
    	ON A.EINZELTEILNR = B.TEILENR
    	inner join stl parts on A.baukastennr = parts.einzelteilnr
    )
    
    
    Insert into [dbo].[TA_Stückl_Be_zeit]
    	(BG,
    	baukastennr,
    	einzelteilnr,
    	bes_zeit,
    	BZ_1,
    	BZ_2,
    	BZ_3,
    	[level],
    	IsNode)
    Select BG,
    		baukastennr,
    		einzelteilnr,
    		be_zeit,
    		BZ_1,
    		BZ_2,
    		BZ_3,
    		[level],
    		case
    			when (
    					(stl.einzelteilnr in (select top(1) baukastennr from TA_STÜCKLISTE where baukastennr = stl.einzelteilnr)) 
    			     ) then 1 else 0
    		end
    from stl
    	
    	fetch next from cur into @BAUKASTENNR
    END
    close cur
    deallocate cur
    Hat jemand eine, oder auch mehrere Ideen, wie man das Ganze performanter gestalten kann.
    Die drei Ausgangstabellen besitzen alle einen PK und mehrere Indizes.

    Gruß
    Gerald

  • #2
    Warum verwendest du einen Cursor und nicht einfach einen INSERT... SELECT? Ist mir gerade zu komplex um das umzubauen kann aber keinen Grund erkennen warum man den Distinct Teilenr nicht auch im INSERT SELECT unterbringen können sollte um dann einfach dieses eine SQL auszuführen.

    Comment


    • #3
      Gibt es bei MS SQL "Bulk" operationen?
      Bei Oracle geht es so:
      Code:
       
      open cur;
      Fetch cur bulk collect into ...
      Kannst du beim INSERT die Spalte "IsNode" NULL lassen und erst am Ende wenn alles eingefügt ist, mit einem Statement updaten?
      Das Select "SELECT Distinct TEILENR FROM TA_TEILE" sollte sich doch auch in das INSERT mit einbauen lassen, dann musst du nicht jede Zeile einzeln einfügen.

      Gruss

      Comment


      • #4
        Hallo,
        Das Select Distinct stellt nur die Daten aller verfügbaren Hauptbaugruppen bereit. In der CTE werden dann alle benötigten Teile und wenn vorhanden die Teile weiterer Unterbaugruppen rekursiv ermittelt. Im Anschluß werden die Daten zu einer Baugruppe in der Tabelle abgespeichert, bevor dann der Cursor die nächste Haptbaugruppe ermittelt. Daher kann das Select Distinct nicht mit in das Insert eingebaut werden, da es überhaupt keine Daten für die Zieltabelle ermittelt, sondern lediglich die Quelle für die CTE darstellt.
        Ich hoffe mal ich habe mich einigermaßen verständlich ausgedrückt.

        Gruß
        Gerald

        Comment


        • #5
          Nö erkenne nicht warum das nicht gehen sollte. Rein von aussen betrachtet sollte man

          [HIGHLIGHT= SQL]where TEILENR = @BAUKASTENNR[/HIGHLIGHT]

          durch ersetzen können.

          [HIGHLIGHT= SQL]where TEILENR in (SELECT Distinct TEILENR FROM TA_TEILE)[/HIGHLIGHT]

          Deine rekursive CTE scheint mir so geschrieben zu sein das die damit richtig umgeht.

          Comment


          • #6
            Hallo Ralf,
            das ist mal ein Versuch wert.

            Comment


            • #7
              Hallo Ralf,
              es sieht so aus, als ob es funktioniert. Ich muß es halt noch genau testen, daß auch alle Werte stimmen.
              Performance war jetzt top (keine Minute mehr).

              Vielen Dank!!!
              Gerald

              Comment

              Working...
              X