2017-08-21 2 views
1

Ich habe zu viele SELECT-Anweisungen zusammen mit nur einem INSERT (vielleicht Hunderte von) Und das System gibt eine schlechte Leistung.INSERT-SELECT (Oracle PL/SQL) - Leistungsproblem

Ich werde im allgemeinen Worten erklären, was passiert und was ich suche:

Unter Berücksichtigung der folgenden zwei Pseudo-Codes in Oracle PL/SQL, die von ihnen würde die beste Leistung geben?

Option A:

INSERT INTO MyTable 
    WITH Fields AS (
    SELECT Field1, Field2, ..., FieldN FROM TableA JOIN TableW .... WHERE <condition1> 
    UNION ALL 
    SELECT Field1, Field2, ..., FieldN FROM TableB JOIN TableX .... WHERE <condition2> 
    UNION ALL 
    SELECT Field1, Field2, ..., FieldN FROM TableC JOIN TableB .... WHERE <condition3> 
    .... 
    UNION ALL 
    .... 
    SELECT Field1, Field2, ..., FieldN FROM TableZZZ JOIN TableB .... WHERE <conditionN> 

Option B:

BEGIN 
    INSERT INTO MyTable SELECT Field1, Field2, ..., FieldN FROM TableA JOIN TableZ .... WHERE <condition1> 
    INSERT INTO MyTable SELECT Field1, Field2, ..., FieldN FROM TableB JOIN TableW .... WHERE <condition2> 
    INSERT INTO MyTable SELECT Field1, Field2, ..., FieldN FROM TableC JOIN TableH .... WHERE <condition3> 
    ... 
    INSERT INTO MyTable SELECT Field1, Field2, ..., FieldN FROM TableZZZZ JOIN TableX .... WHERE <conditionN> 
END 

ich nicht die wirklichen Tabellennamen gelegt hat, aber ich würde gerne wissen: wenn ich die aktuelle Option A Option ändern B, würde es mir eine bessere Leistung präsentieren? Ich meine, ist es eine gute Idee, UNION ALL in diesem Fall durch viele INSERT-Anweisungen zu ersetzen?

+0

Warum nicht 'WO ODER ODER ...'? –

+0

@PeterLang, ist groß und diese SELECT-Anweisungen variieren oft (ich werde den Pseudo-Code aktualisieren) –

+0

Dies beantwortet Ihre Frage nicht, aber wenn ein Redesign eine Option ist, stellen Sie sicher, dass 'TableA',' TableB' und ' TableC' müssen wirklich separate Tabellen sein. Ihre aktuelle Anforderung (und möglicherweise viele andere) könnte viel einfacher gelöst werden, wenn es eine einzige Tabelle mit einer Spalte gibt, die den Typ beschreibt. –

Antwort

2

Context Switches und Leistung

Fast jedes Programm PL/SQL-Entwickler schreiben sowohl PL/SQL und SQL-Anweisungen. PL/SQL-Anweisungen werden vom PL/SQL-Anweisungs-Executor ausgeführt. SQL-Anweisungen werden vom SQL-Anweisungs-Executor ausgeführt. Wenn das PL/SQL-Laufzeitmodul eine SQL-Anweisung findet, wird die SQL-Anweisung an die SQL-Engine übergeben. Die SQL-Steuerkomponente führt die SQL-Anweisung aus und gibt Informationen an die PL/SQL-Steuerkomponente zurück (siehe Abbildung 1). Diese Übertragung der Kontrolle wird als Kontextwechsel bezeichnet, und jeder dieser Switches verursacht Overhead, der die Gesamtleistung Ihrer Programme verlangsamt.

so, diese dritte Art und Weise verwenden:

create view MyView as select Field1, Field2, ..., FieldN from TableA join TableB .... where <condition1> 

declare 
    p_array_size pls_integer := 100; 
    type   array is table of MyView%rowtype; 
    l_data  array; 
    cursor c is select * from MyView;  
begin 
    open c; 
    loop 
    fetch c bulk collect into l_data limit p_array_size; 

    forall i in 1..l_data.count 
    insert into MyTable values l_data(i); 

    exit when c%notfound; 
    end loop; 
    close c; 
end; 
+0

Sie sollten erklären, was diese Technik ist und warum dies zu einer besseren Leistung führen könnte. –

+0

@ J.Chomel ok, danke, ich habe meins bearbeitet. –

+0

Ihre Lösung ist interessant. Aber meinst du, Option A ist besser? noch unklar. (+ Ich sehe keine Ziffer 1 in Ihrer Antwort). –

0

Außer Ihren Fragen sind sehr eigenartig in Bezug auf Speicher auf Ihrem Datenbankserver, die Option B wird nicht die Leistung der großen Abfrage zu erhöhen.

Um sicherzustellen, dass das obige Problem zutrifft, fragen Sie Ihren Datenbankadministrator, ob er zu dem Zeitpunkt, zu dem Sie die Abfrage durchführen, in Ihrem databsae sever SGA vorgeht. Wenn ein Stau im Speicher auftritt, sollten Sie versuchen, die Option B zu implementieren.

Wenn ich "Speicherstaus" sage, meine ich, dass der gesamte SGA-Speicher voll ist, was einen Tausch auf dem Server notwendig macht. Wenn Sie die Inserts in einer Sequenz ausführen, kann SGA zwischen den Inserts wiederverwendet werden.