Announcement

Collapse
No announcement yet.

PL/SQL-Loop zu langsam

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

  • PL/SQL-Loop zu langsam

    Hallo Kollegen,

    ich könnte mal Eure Hilfe gebrauchen. Den folgenden Loop habe ich geschrieben

    DECLARE

    d number(38) := 0;
    e number(38) := 100000;

    scr_start TIMESTAMP(9);
    scr_ende TIMESTAMP(9);
    scr_dauer INTERVAL DAY TO SECOND;

    BEGIN

    scr_start := SYSTIMESTAMP;

    FOR i IN 1..e LOOP

    d := i;

    DBMS_OUTPUT.PUT_LINE(d);

    END LOOP;

    scr_ende := SYSTIMESTAMP;

    scr_dauer := scr_ende - scr_start;

    DBMS_OUTPUT.PUT_LINE('Dauer: '||scr_dauer);

    END;
    /


    Obwohl der Loop sehr einfach ist und innerhalb der Schleife fast nichts passiert, dauert die Antwort von der DB ewig (mehrere Minuten). Allein die 100000 Durchläufe können m.E. die Dauer nicht verursachen. Kann es sein, dass mein DB-Schema in der Performance begrenzt wurde? Wie kann ich das ggf. herausfinden.

    Besten Dank erstmal und viele Grüße

  • #2
    Hast du mal versucht, dein Script ohne Serveroutput durchlaufen zu lassen?
    Wenn ich die Ausgabe innerhalb der Schleife ausstelle, geht das ganze ruck zuck. Lass ich mir aber die Nummern ausgeben geht alles in die Knie.

    Code:
    Dauer: +00 00:00:00.035354
    
    PL/SQL procedure successfully completed
    Wäre vielleicht mal einen Versuch wert. Es wir nämlich nicht direkt die Ausgabe gemacht. Sie wird erst zwischengespeichert und dann nach dem ausführen ausgegeben. Das kostet Zeit.

    Comment


    • #3
      Hallo JenneB,

      vielen Dank, ohne Ausgabe geht es tatsächlich viel schneller. Ist es nur diese Ausgabe, die die Schleife so ausbremst? Was ist wenn ich innerhalb der Schleife etwas konkatenieren und anschl. vergleichen möchte?

      Gruß Pat

      Comment


      • #4
        Hallo,

        jede Verarbeitung braucht seine Zeit. Das Zwischenspeichern von Ausgaben jedoch besonders lange, da Sie erst komplett in einen Buffer geschrieben werden und ganz am Ende des Skriptes auf der Konsole ausgegeben werden.
        Bei deinen 100000 Zeilen kann man sich vorstellen, das das etwas Zeit und Speicher in Anspruch nimmt.

        Meines Wissens kannst du ohne Probleme in der Schleife rechnen und nachher damit weiterarbeiten. Hier wird ja nichts in dem Buffer geschrieben.

        Gruß

        Jens

        Comment


        • #5
          Hallo nochmal,

          ich habe noch eine andere Frage zu der Schleife.

          Beim Versuch die Schleife 10 Mrd. mal auszuführen, erhalte ich die Fehlerausgabe ORA-01426 numerischer Überlauf. Offensichtlich ist i begrenzt. Zu dem Fehler habe ich gelesen, dass man entweder die Anzahl verringern soll oder sicherstellen soll, dass der Wert nicht unendlich groß ist(wird). Man kann zwar trotzdem 10 Mrd Schleifendurchläufe erzeugen, indem man in einen 1 Mrd. Loop einen 10er Loop legt, aber es handelt sich ja um einen anderen loop. Kann man i erweitern?

          Comment


          • #6
            Also bei mir geht's. Vielleicht hast du i nicht groß genug deklariert.

            Code:
            declare
                   i number(38) := 0;
            begin
                 for i in 0..1000000000 loop
                     null;
                 end loop;
            end;
            /

            Comment


            • #7
              leider fehlt eine Null und bei dem im Deklarationsteil enthalten i handelt es sich m.E. um ein anderes (weiteres) i da das i in der schleife nur dort gilt ;-)
              habe es natürlich trotzdem probiert und leider bleibt der Fehler

              Comment


              • #8
                Oh, sorry, hab mich verguckt.

                Versuch es doch mal mit einem pseudo i. D.h. du verschachtelst einfach zwei For-Schleifen und deklarierst das pseudo i so groß, das es 10 Mrd aufnehmen kann.

                Beispiel:
                Code:
                set serveroutput on size 10000;
                declare
                       pseudo_i number(38) := 0;
                       
                       scr_start TIMESTAMP(9);
                       scr_ende TIMESTAMP(9);
                       scr_dauer INTERVAL DAY TO SECOND;
                       
                begin
                     scr_start := SYSTIMESTAMP;
                     
                     for i in 0..9 loop
                         for j in 0..999999999 loop
                             pseudo_i := pseudo_i + 1;
                         end loop;
                     end loop; 
                     
                     dbms_output.put_line( 'Fertig:' || pseudo_i );
                     scr_ende := SYSTIMESTAMP;
                     scr_dauer := scr_ende - scr_start;
                     DBMS_OUTPUT.PUT_LINE('Dauer: '||scr_dauer);
                end;
                /
                So erhälst du ein Schleifenkonstrukt, das 10 Mrd. mal durchläuft.

                Code:
                Fertig:10000000000
                Dauer: +00 00:29:58.597251

                Comment

                Working...
                X