2011-12-30 12 views
2

日付、オブジェクト名、およびコードで構成された非常に大きなテーブルで、一連のトランザクションの最初、最後、最大および最低価格を検索する手順があります。私はまた取引量の合計が必要です。テーブルには約30億行があり、この手順には実行に数日かかる。私はできるだけその時間を短縮したいと思います。私はトランステーブルの別個のフィールドにインデックスを持ち、クエリの選択された部分についての説明を見て、インデックスが使用されています。私は、代替的なアプローチに関する提案には開いています。私はOracle 11g R2を使用します。ありがとうございました。Oracle 11gの最適化手順

declare 
    cursor c_iter is select distinct dt, obj, cd from trans; 
    r_iter c_iter%ROWTYPE; 
    v_fir number(15,8); 
    v_las number(15,8); 
    v_max number(15,8); 
    v_min number(15,8); 
    v_tot number; 
    begin 
    open c_iter; 
    loop 
     fetch c_iter into r_iter; 
     exit when c_iter%NOTFOUND; 

     select max(fir), max(las) into v_fir, v_las 
     from 
      (select 
       first_value(prc) over (order by seq) as "FIR", 
       first_value(prc) over (order by seq desc) as "LAS" 
       from trans 
       where dt = r_iter.DT and obj = r_iter.OBJ and cd = r_iter.CD); 

      select max(prc), min(prc), sum(qty) into v_max, v_min, v_tot 
      from trans 
      where dt = r_iter.DT and obj = r_iter.OBJ and cd = r_iter.CD; 

      insert into stats (obj, dt, cd, fir, las, max, min, tot) 
      values (r_iter.OBJ, r_iter.DT, r_iter.CD, v_fir, v_las, v_max, v_min, v_tot); 

      commit; 
    end loop; 
    close c_iter; 
end; 

答えて

7
alter session enable parallel dml; 

insert /*+ append parallel(stats)*/ 
into stats(obj, dt, cd, fir, las, max, min, tot) 
select /*+ parallel(trans) */ obj, dt, cd 
    ,max(prc) keep (dense_rank first order by seq) fir 
    ,max(prc) keep (dense_rank first order by seq desc) las 
    ,max(prc) max, min(prc) min, sum(qty) tot 
from trans 
group by obj, dt, cd; 

commit; 
  • 単一のSQL文は通常、複数のSQL文よりも大幅に高速です。一時的な表スペースのように、より多くのリソースが必要になることもありますが、別のカーソルがすでにディスク上の表全体をすでにソートしている可能性があります。
  • パラレルDMLおよびパラレル問合せを有効にすることもできますが、オブジェクトおよびシステムの設定によっては、これがすでに発生している可能性があります。 (あなたのリソースによっては、必ずしも良いことではないかもしれませんが、通常は大きなクエリに役立ちます。)
  • SQLが大量のデータを書き込む場合、パラレル書き込みとAPPENDはパフォーマンスを向上させるはずですが、テーブルは次のバックアップまで回復できません。 (パラレルDMLは、自動的にダイレクトパスが書き込みを使用しますが、私は通常、並列処理が正しく動作しません。念のためにとにかくAPPEND含まれています。)

さえ、このような小さなクエリのために、考慮すべき多くがありますが、これはありますどこから始めるのですか?

+0

これは非常にエレガントなソリューションですありがとうございます。私は現在のスクリプトと手続きの時間を合わせて報告します。 –

+0

このSQLは3時間で実行され、3日間で実行されました。私は絶対に驚いています。助けてくれてありがとう。相談しますか? –

+0

パラレルクエリはEnterprise Editionでのみライセンスされていることに注意してください。それは銀色の弾丸でもありません。 – APC

2

ない私は与えたいと思い固体の答えが、考慮すべきいくつかのこと:

最初はbulk collectを使用することでしょう。しかし、あなたが11gを使用しているので、うまくいけば、これはすでにあなたのために自動的に行われています。

1回の繰り返しごとにコミットする必要がありますか?私は間違っているかもしれませんが、これを推測しているのはあなたのトップタイム消費者の一人です。

最後に、ジョーンズの答えは+1です。 (すべてを単一のSQLクエリに書くことができるかどうかはわかりませんでしたが、これも同様に提案するつもりでした)。

+1

2kのようなものに数えて、各間隔の後にコミットできます。 – Alfabravo

+1

これはおそらく良い考えではありません。オープン・カーソルを使用してコミットすると、ORA-1555エラーが発生する可能性があります。また、この場合、selectとinsertの間で処理が行われず、@jonearlesによって記述された... into ... into ...の挿入が明確な勝者です。 –

0

クエリを並行して実行しようとすると、合理的なOracleホワイトペーパーhereを参照してください。これは私が今まで自分で使用していたOracleの機能ではありませんので、初めての経験はありません。また、作成する並列プロセスを実行できるように、Oracleサーバーには十分なリソースが必要です。