2010-12-22 17 views
1

Wie kann ich Ausführungsplan für eine Oracle-Loop-Abfrage erzeugen wie unten:wie Ausführungsplan für Oracle-Schleife erzeugen

BEGIN 
    FOR L IN (SELECT FIRST_NAME, LAST_NAME, SOME_ID FROM TABLE1) 
    LOOP 
     INSERT INTO TABLE2 (FIRSTNAME, LASTNAME) 
     (SELECT FNAME, LASTNAME FROM TABLE2 WHERE SOME_ID = L.SOME_ID) 

    V_CNT := V_CNT + 1; 

    IF (MOD(V_CNT, 1000)=0) THEN 
    COMMIT; 
    END IF; 

END LOOP; 

Wie kann ich Ausführungsplan für einen Block wie oben erzeugen?

Ich fragte ähnliche Frage earlier und entschied, Blöcke aus meiner gespeicherten Prozedur zu extrahieren und Ausführungspläne für die einzelnen zu generieren. Obwohl ich weiß, wie man Pläne für einfache Abfragen generiert, weiß ich nicht, wie man sie für Schleifenblöcke wie oben erzeugt.

Antwort

1

Sie können keine Ausführungspläne für PL/SQL Blöcke generieren, nur für Abfragen.

Ausführungsplan zeigt, wie deklarative Befehle (SQL) unter der Haube ausgeführt werden, i. e. Welche Verfahren werden verwendet? Es transformiert die deklarativen Konstrukte (set operations) in Prozeduren (Nested Loops, Hash Joins, Sortierungen etc.).

PL/SQL, ist, wie der Name schon sagt, eine prozedurale Sprache, definiert den Ausführungsplan selbst - geschachtelte Schleifen in Ihrem Fall.

Wenn Sie den Ausführungsplan für die innere Abfrage sehen möchten, sollten Sie es kopieren und EXPLAIN PLAN FOR …

Hinweis ausgeben, dass diese effizienter als neu beschrieben werden kann:

BEGIN 
     FOR L IN 
     (
     SELECT MIN(some_id) AS minid, MAX(some_id) AS maxid 
     FROM (
       SELECT some_id, rownum AS rn 
       FROM (
         SELECT some_id 
         FROM table1 
         ORDER BY 
           some_id 
         ) 
       ) 
     GROUP BY 
       TRUNC(rn/1000) 
     ) 
     LOOP 
       INSERT 
       INTO TABLE2 (FIRSTNAME, LASTNAME) 
       SELECT FNAME, LASTNAME 
       FROM table1 
       JOIN table2 
       ON  table2.some_id = table1.some_id 
       WHERE table1.some_id BETWEEN l.minid AND l.maxid 
       V_CNT := V_CNT + 1; 
       IF (MOD(V_CNT, 1000)=0) THEN 
         COMMIT; 
       END IF; 
     END LOOP; 
END; 
+0

ok.Sagen wir, wenn ich die obige Abfrage aus einer Schleife nehme und es einfach nur eine Abfrage mache und den Ausführungsplan erzeuge. Wenn ich diesen Ausführungsplan analysieren würde, wäre es vergleichbar mit dem, wenn die gleiche Abfrage in einer Schleife ausgeführt wird und ein Insert jemals 1000 Recods festlegt? –

+0

@learn_plsql: Ja, plus der Overhead des Umschaltens zwischen 'SQL' und' PL/SQL'. Warum benutzen Sie nicht einfach einen Join? – Quassnoi

+1

oh das ist eine andere Geschichte über nicht mitmachen. Es fügt Millionen von Abfragen in die Tabelle ein, so dass wir von unserer dba angewiesen wurden (mehr wie aufgezwungen), Schleifen zu verwenden. –

3

Ihr PL/SQL-Block kann in SQL neu geschrieben werden:

INSERT INTO table2 (firstname, lastname) 
    SELECT fname, lastname 
    FROM table2 
    WHERE some_id IN (SELECT some_id FROM table1); 

Sie können dann den obigen INSERT "Plan erklären".

Wenn Sie Batch-Commits durchführen müssen, dann ist die Verwendung von BULK COLLECT ... LIMIT und FORALL effizienter als ein Cursor für die Schleife, besonders wenn Sie Millionen von Zeilen verarbeiten. Nützliche Links:

+0

Ich glaube, er will Zwischen-Commits. Auf einem riesigen Tisch kann das aus dem "UNDO" -Raum herauslaufen. – Quassnoi

+0

Ah! Dann glaube ich, BULK COLLECT ... LIMIT/FORALL ist eine gute Lösung. –

1

Wenn Sie in der Leistung Ihres Verfahrens PL/SQL-Code interessiert sind Sie PL untersuchen kann/SQL-Profilerstellung

Der Profiler ermöglicht Ihnen, Informationen über die Laufzeitleistung Ihres PL/SQL zu sammeln. Nachdem der Profilierungslauf abgeschlossen ist, können Sie über die Ergebnisse berichten und Informationen anzeigen, wie oft jede Zeile ausgeführt wurde, durchschnittliche Ausführungszeit jeder Zeile. Dies kann Ihnen bei der Identifizierung von Engpässen helfen und Sie auf die ersten Punkte hinweisen, die möglicherweise optimiert werden müssen.

Ihr größter potenzieller Gewinn besteht darin, den Code mit der schlechtesten Leistung zu betrachten, damit er besser läuft. Sobald dies verbessert wurde, profilieren Sie sich erneut, um Ihre Verbesserungen zu überprüfen und die nächste Anweisung zu finden, die möglicherweise beachtet werden muss.

Eine gute erste einführung ist hier: Oracle's DBMS Profiler

Verwandte Themen