2017-11-04 8 views
1

Oracle(11g)上で実行するようにSQL Serverシステムを変換しています。システムはすべて設定されており、データが読み込まれています。データの量はかなり大きい(テーブルなどで160mのレコード)。サーバーは、1tb raid 1 + 0と96gbのメモリを搭載したHP DL380です。pl/sqlがカーソルより遅い

テストでは、3-4テーブルを使用するSQL挿入ステートメントが90分以上実行されますが、カーソルを使用する同じロジックは約3分かかります。

これは、カーソルの場合は約8分、SQL ServerのSQLの場合は2-3分かかります(これは私が期待しています)。

つまり、Oracle SQLのカーソルはカーソルの30-50倍です。これは、OracleシステムがOLTP(個々のレコードの挿入)では非常に高速ですが、SQLではより大きなテーブルを操作するのが本当に遅いという印象を与えてくれます。

私はこれが通常のケースではないと確信していますので、調整する必要があるOracleのパラメータはありますか?以下

が使用SQLの例である:

INSERT INTO TMP_TXN ...... 
SELECT ....... 
    FROM TXN (160m rows), CUSTOMERS (1m rows), PRODUCTS (1k rows) 
WHERE TXN.TXN_DATE = p_date 
    AND TXN.TXN_AMOUNT > 0 
    AND TXN.PRODUCT_ID = PRODUCTS.PRODUCT_ID 
    AND PRODUCTS.PRODTYPE_ID IN ('1', '12', '13'); 
    AND TXN.CUSTOMER_ID = CUSTOMERS.CUSTOMER_ID 
    AND CUSTOMERS.CUSTOMER_STATUS LIKE 'A%' 

FOR item IN (SELECT ..... 
       FROM TXN (160m rows), CUSTOMERS (1m rows), PRODUCTS (1k rows) 
       WHERE TXN.CUSTOMER_ID = CUSTOMERS.CUSTOMER_ID 
       AND CUSTOMERS.CUSTOMER_STATUS LIKE 'A%' 
       AND TXN.PRODUCT_ID = PRODUCTS.PRODUCT_ID 
       AND PRODUCTS.PRODTYPE_ID IN ('1', '12', '13') 
       AND TXN.TXN_DATE = p_date 
       AND TXN.TXN_AMOUNT > 0 
       ORDER BY CUSTOMER_ID); 
    LOOP   
    IF item.customer_id <> customer_id_old THEN 
    etc. 

(TXN上の)インデックスはCUSTOMER_IDとTXN_DATEためのものです。 TMP_TXNの索引は、CUSTOMER_ID(およびこのスクリプトでは不要ないくつかのもの)用です。

この例のSQLについては諦めてください。それは文字通り数百のうちの1つであり、すべての単一のスクリプトは遅く実行されますが、カーソルを使用すると、スクリプトは10〜50倍速く実行されます。 SQLを実行するとき、私はリソース・モニタを見て、UNDO/REDO表領域が3〜50MB /秒であるのに対し、データ表領域はほとんど触られていない(1MB /秒)ことを確認します。 REDOログファイルは、以前は約1〜2秒ごとに切り替わっていたので、10GBにリサイズされました!

これは完全に間違っているので、私が逃したいくつかのOracleセットアップの問題があると思います。 Oracle SQLからのこの信じられないほど優れたパフォーマンスのアイデアはありますか?

+0

システムには、実行ごとにバッファがクリアされるなど、キャッシングの違いはありません。 – Kingbeard

+0

SQLを実行しているときにパフォーマンスモニタを見ると、ディスクのデータスループットは1mb /秒でしたが、カーソルは70mb /秒でした。 – Kingbeard

+0

魔法の 'set fast = true'パラメータはありません。優れたパフォーマンスは、Oracleの理解から生まれたものです。結果は自然ではなく、何かが欠けていると考えることは正しいです。これらのクエリをサポートするためにこれらすべてのテーブルで合理的なインデックスを作成しましたか?統計を集めましたか? –

答えて

0

Oracleでライブバックアップを必要としない大規模なバッチ処理を行う場合は、REDOの書き込みをスキップするDirect Load Insertを使用することを検討できます。

INSERT /*+ append nologging */ INTO TMP_TXN ... 
SELECT ... 

表領域ではなく、新しい行を挿入するための十分な大きさの空のブロックを探して、あなたのテーブルの位置の現在の終わりである「ハイウォーターマーク」の後ろに書くことの問題を追加します。データベースの設定に応じて、ダイレクトロード作業を行う必要があります。more info hereテーブルのDDLに定義することは必須ではありません。おそらくすべてのアクションでそれを必要としないからです。

p_dateのパラメータは、PL/SQLプロシージャ内で両方を使用するように見えますか? plsqlエンジンとSQLエンジンの間で切り替えることに注意してくださいhas an impact on the performance。 A FORステートメントは、処理する前に数百行をフェッチしていくつかの利点を与えますが、挿入は依然として行ごとに行われます。

この例は、お客様1人当たりn個のインサートと1個のインサートだけでなく、CUSTOMERSに支持的なインデックスがないようですが、そのことに集中しないようにお願いしました。

+0

ご意見ありがとうございます。すべてのスクリプトはストアドプロシージャの一部です。 私はテーブルnologgingと/ * + append * /を試しました。これは物事をより速くしましたが、それほど多くはありませんでした。 SQLはカーソルループよりもずっと遅いです。 両方のステートメントで同じ結果が得られます(一部のみ図示)。 また、すべてのテーブルに適切なインデックスがあります。 – Kingbeard

関連する問題