2017-08-21 12 views
1

INSERTが1つだけ(多分数百件)のSELECTステートメントが多すぎます。システムのパフォーマンスが低下しています。INSERT-SELECT(Oracle PL/SQL) - パフォーマンスの問題

私は何が起こっているのか、私が探してるものを一般的な言葉で説明します:

は、Oracle PL/SQLで次の二つの擬似コードを考慮すると、最高のパフォーマンスを与えるそれらのどれ?

オプション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> 

オプション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 

私は、実際のテーブル名を入れていないが、私は知っているしたいと思います:私はオプションに現在のオプションAを変更した場合B、それは私に良いパフォーマンスを提示するだろうか?つまり、この場合、UNION ALLを多くのINSERT文で置き換えるのは良い考えですか?

+0

なぜ「WHERE OR OR ...? –

+0

@PeterLang、は大きく、これらのSELECT文は頻繁に変更されます(私は擬似コードを更新します) –

+0

これはあなたの質問に答えませんが、再設計がオプションである場合、 'TableA'、' TableB'、 TableCは本当に別のテーブルである必要があります。タイプを記述する1つのカラムを持つ1つのテーブルがあれば、あなたの現在の要件(および他の多くのもの)はもっと簡単に解決できます。 –

答えて

2

コンテキストスイッチとパフォーマンス

PL/SQLの開発者が書くほぼすべてのプログラムは、PL/SQLおよびSQL文の両方を含んでいます。 PL/SQL文はPL/SQL文実行プログラムによって実行されます。 SQLステートメントは、SQLステートメント実行プログラムによって実行されます。 PL/SQLランタイム・エンジンがSQL文を検出すると、PL/SQLランタイム・エンジンは停止し、SQL文をSQLエンジンに渡します。 SQLエンジンはSQL文を実行し、情報をPL/SQLエンジンに戻します(図1参照)。この制御の転送はコンテキストスイッチと呼ばれ、これらのスイッチのそれぞれがプログラムの全体的なパフォーマンスを低下させるオーバーヘッドを招きます。

ので、この第三の方法で使用します。クエリを除き

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

この手法が何であるか、そしてなぜこれがより良いパフォーマンスにつながるのかを説明する必要があります。 –

+0

@ J.Chomel ok、ありがとう、私は私の編集しました。 –

+0

あなたのソリューションは面白いです。しかし、オプションAが優れていることを意味しますか?まだ不明です。 (+あなたの答えに数字1は表示されません)。 –

0

は、データベース・サーバ上のメモリの面で非常に固有で、オプションBは大きなクエリのパフォーマンスを向上させるつもりはありません。

上記が正しいことを確認するには、照会を実行する際にdatabsae sever SGAで何が起きているかをDBAに確認してください。メモリの詰まりが発生した場合は、オプションBを実装する価値があります。

「メモリー・ジャム」と言うと、私はSGAメモリー全体がいっぱいで、サーバー上でスワップが必要であることを意味します。シーケンスでインサートを実行すると、インサート間でSGAを再利用できます。

関連する問題