web-dev-qa-db-ja.com

すべての行を更新

1つの列に対して非常に大きなOracleテーブルのすべての行を更新する最も効率的な方法を知りたいです。例えば:

update mytable set mycolumn=null;

または:

update mytable set mycolumn=42;

私の知識はとても古くなっているかもしれません。列を削除するようにテーブルを変更します。次に、テーブルを変更して、使用する新しい値のデフォルト値を持つ列を追加します。次に、テーブルを変更して、列のデフォルト値を削除します。これはアップデートを実行するよりもはるかに高速であると思いますが、もっと良い方法があると感じています。

12
kainaw

この一括更新を行っている間、このテーブルに対して行われている他のアクティビティに大きく依存します。あなたがしたいことのいくつかのサンプルを実行して、どちらが最良の方法であるかを知ることができるある種のテスト環境があることを願っています。私はしようとします:

  1. シングルupdate table set column_name = blah;
  2. PlSqlループを作成して、テーブル内のすべての主キーを選択し、それらをループします。updating the column=blahおよびすべてのX更新をコミットします(多分10000)。このコードをコピーして並列化し、主キーの別のセクションをコピーさせることができます。

OLTPシステムで非常にアクティブに使用されているテーブルで非常に類似した問題があり、5回並列化して実行でき、100以上のMM行テーブルのコミットにユーザーロックの影響はありませんでした。 10000ごと。テーブルのサイズや実行しているアプリケーションの種類については言いませんでしたが、この種類のソリューションが適しているかもしれません。

2
Pete Hagerty

高速なUPDATEを実行するには、起動しているトリガーがないことを確認してください。

SELECT trigger_name, status FROM user_triggers WHERE table_name = 'MYTABLE';

ALTER TABLE mytable DISABLE ALL TRIGGERS;

完了したら、必要なものだけを再度有効にしてください。

ALTER TRIGGER mytrigger ENABLE;

また、インデックスのメンテナンスのオーバーヘッドに直面している可能性があります。インデックスを個別に再構築してみてください。これを行うには、pappesによるここでの回答が役に立ちます: https://stackoverflow.com/questions/129046/disable-and-later-enable-all-table-indexes-in-Oracle

参考までにここでパップの答えを繰り返します。 (このSPOOLコマンドは、ご使用のプラットフォームと環境を想定していることに注意してください。)

set pagesize 0    
alter session set skip_unusable_indexes = true;
spool c:\temp\disable_indexes.sql
select 'alter index ' || u.index_name || ' unusable;' from user_indexes u;
spool off
@c:\temp\disable_indexes.sql

インポートします...

select 'alter index ' || u.index_name || ' rebuild online;'
  from user_indexes u;
0
durette