2

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

    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;
4

3 に答える 3

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 を含めます。)

このような小さなクエリであっても、考慮すべきことはたくさんありますが、ここから始めます。

于 2011-12-30T17:02:28.077 に答える
2

私が伝えたい確かな答えではありませんが、考慮すべきいくつかのことがあります。

1つ目は、一括収集を使用することです。ただし、11gを使用しているので、これがすでに自動的に行われていることを願っています。

すべての反復の後に本当にコミットする必要がありますか?私は間違っているかもしれませんが、これはあなたのトップタイムの消費者の一人だと思います。

最後に、jonearlesの答えは+1です。(すべてを単一のSQLクエリに書き込めるかどうかはわかりませんでしたが、これも提案するつもりでした。)

于 2011-12-30T16:14:58.777 に答える
0

クエリを並行して実行してみることができます。これについては、妥当なOracleホワイトペーパーがあります。これは私が今まで自分で使用しなければならなかったOracleの機能ではないので、それを直接体験したことはありません。また、これによって作成される並列プロセスを実行できるように、Oracleサーバー上に十分なリソースを解放する必要があります。

于 2011-12-30T16:43:17.650 に答える