2012-01-03 11 views
1

2つの変数を追跡するために、大きなテーブル(2.5Bレコード)を行単位で処理する必要があります。想像できるように、これはかなり遅いです。私はこの手順をどのように調整するかについてのアイデアを探しています。ありがとうございました。Oracle 11gで行(カーソル)処理を最適化する

declare 
    cursor c_data is select /* +index(data data_pk) */ * from data order by data_id; 
    r_data c_data%ROWTYPE; 
    lst_b_prc number(15,8); 
    lst_a_prc number(15,8); 
begin 
    open c_data; 
    loop 
     fetch c_data into r_data; 
     exit when c_data%NOTFOUND; 

     if r_data.BATS = 'B' then 
      lst_b_prc := r_data.PRC; 
     end if; 
     if r_data.BATS = 'A' then 
      lst_a_prc := r_data.PRC; 
     end if; 
     if r_data.BATS = 'T' then 

      insert into trans .... lst_a_prc , lst_b_prc  
      end if; 
    end loop; 
    close c_data; 
end; 

問題は本当にダウンしたときにBATSは= 'A' と各BATSについてBATSの= 'B' = 'T' レコード最新のPRC値を追跡するために、効率的なSQLを見つけることになります。

答えて

1

私はこのようなデータのテーブルで、正しく問題を理解していれば:

create table data as 
select 1 data_id, 'T' bats, 1 prc from dual union all 
select 2 data_id, 'A' bats, 2 prc from dual union all 
select 3 data_id, 'B' bats, 3 prc from dual union all 
select 4 data_id, 'T' bats, 4 prc from dual union all 
select 5 data_id, 'A' bats, 5 prc from dual union all 
select 6 data_id, 'T' bats, 6 prc from dual union all 
select 7 data_id, 'B' bats, 7 prc from dual union all 
select 8 data_id, 'T' bats, 8 prc from dual union all 
select 9 data_id, 'T' bats, 9 prc from dual; 

あなたが見えるAとBの最後のPRC値を使用して、各Tごとに1行を挿入したいですこのような何か:

T data_id Last A Last B 
--------- ------ ------ 
1   null  null 
4   2  3 
6   5  3 
8   5  7 
9   5  7 

は、このクエリは動作するはずです:

select data_id, last_A, last_B 
from 
(
    select data_id, bats, prc 
     ,max(case when bats = 'A' then prc else null end) over 
      (order by data_id 
      rows between unbounded preceding and current row) last_A 
     ,max(case when bats = 'B' then prc else null end) over 
      (order by data_id 
      rows between unbounded preceding and current row) last_B 
    from data 
) 
where bats = 'T'; 

そんなにデータでは、あなたの」おそらくダイレクト・パスの書込みと並列処理を使用したいと思うでしょう。 パフォーマンスは、解析関数のソートがメモリまたはディスクで実行できるかどうかによって大きく異なります。メモリーを最適化することは非常に難しいかもしれませんが、おそらくDBAを使用して他のプロセスに問題を引き起こすことなく、できるだけ多くのメモリーを使用できるようにする必要があります。

+0

ありがとうございます。これはまさに私が必要とするもののように見えます。私は開発サーバー上でテストし、パフォーマンスを報告します。 –

1

いくつかのオプションがあります。最も重要なのは、おそらくあなたのすべての挿入物に対して膨大なUNDO/REDOログを保持しているということです。あなたは、時々、あなたの仕事をコミットすることができます。

もう1つの方法は、SQL MERGEステートメント(またはより簡単なINSERT .. SELECT ..ステートメント)を使用して、Oracleインスタンスが単一のレコードではなくセットで操作できるようにすることです。あなたの選択の実行計画は最適なINSERTのパフォーマンスのために最適化されるかもしれません。

+0

巨大なUNDO表領域については正しいですか。私は、この手順に対応するために300GB近くのbigfileテーブルスペースを作成しました。 SQL MERGEは興味深いようです。私はこれを正確にどのように適用するか分からない。 BATS = 'T'レコードごとにBATS = 'A'とBATS = 'B'のときに最新のPRC値を追跡する効率的なSQLを見つけることには、実際問題があります。 –