2017-11-16 6 views
0

SQLクエリでテーブルを更新しようとしています。私のテーブルには50万レコードあり、10分ほどかかっています。それは私の開発環境です。ベーステーブルを垂下させずにoracleの大きなテーブルを更新する

私がUATに行くかprodすると、テーブルにはdev環境よりも多くのデータが格納されます。テーブル全体を更新してからコミットすると、大量のメモリが消費されます。誰かが私にバッチでテーブルを更新する良い方法を提案することができます。

私はネットを使いましたが、私が見つけた最も一般的な解決策は、「new_tableをold_tableからselect(update)として作成する」という新しいテーブルを作成することです。しかし、私の場合、私は私の環境下で私はテーブルを作成して削除することはできませんので、これを使用することはできません。

ありがとうございました Ankit。

+0

行数が> 0に更新されている間に、ループ内で10000のバッチでそれらを更新します。ループ内でコミットすると、ロールバックが中断され、途中で停止すると途中で停止することがあります。 –

+0

こんにちはAb Bennett、私はコンテキストスイッチを避けようとしているのでPL/SQLに入りたいとは思わない。 –

+0

スイッチングと大きな違いは、正しいバランスを見つけようとしていることです。あなたの質問に答えるために、pl/swlを使うことができず、また新しいテーブルを使うこともできないならば、あなたの唯一のオプションは一つの更新です。あなたは大きなロールバックセグメントを持っていることを確認してください。あなたが宇宙を使い果たすと、あなたは失望するでしょう。あなたがすべての行をやっていないならば、記録のために、コンテクストの切り替えは大したことではありません。 10ミルの行テーブル、100kのチャックで更新、100コミット/スイッチ –

答えて

1

CTASが最も速いオプションです。元のテーブルを削除する必要はありません。名前を変更して保持するだけで管理者を満足させることができます。

それ以外の場合は、状況によってはいくつかの選択肢があります。

の場合:

  • 懸念だけで経過時間についてです。
  • あなたはEnterprise Editionライセンスを所有しています。そして
  • 生産は、その後、あなたが問題を解決するために、パラレルDMLを検討することもでき

を惜しまするCPUを持っています。

alter session enable parallel dml; 

update /*+ parallel (your_table) */ your_table 
set .. 

あなただけのStandard Editionを持っていますが、並行してPL/SQLジョブを実行するDBMS_PARALLEL_EXECUTEパッケージを使用することができ11gR2の上や高い場合。 CPUに関する注意事項は引き続き適用されます。

それを超えると、WHERE句の効率を調べる必要があります。 UPDATEもスキャンで、他のクエリと同様にチューニングできます。

更新プログラムをバッチに分割すると、合計経過時間が長くなります。もちろん、あなたはもっと仕事をしています。単一の更新ステートメントに対するバッチ処理の主な利点は、タスクが途中で終了した場合に、作業を失わないレコードのまとまりをコミットすることです。これは、更新されたレコード(このタスクによって更新されるステータス列または日付列)を区別するためのメカニズムがある場合にのみ有効です。と他のものはです。あなたがそのような旗を持っていないなら、あなたは絶対にテーブルを壊す危険があります。

バッチ処理の最も簡単な方法は、単純なPL/SQLループです。あなたが更新する万行を持っていると仮定すると:

begin 
    for idx in 1..100 loop 
     update your_table 
     set whatever = whatever * 1.1 
        , status = 'touched' 
     where status != 'touched' 
      and rownum <= 10000; 
      commit; 
    end loop; 
end; 

あなたの更新ルールは、彼らが手続きを要求することを十分に複雑である場合を除き明らかにあなたは、いくつかのエラー処理をする必要がありますおそらくログインする、などしかしbulk collectforallなどのルアーに抵抗論理。

関連する問題