数十億のレコードを含むテーブルがあり、条件なしで 1 つのフィールドを更新するだけで済みます。
update <table name> set flag='N'
これは私の更新クエリです。非常に長い時間がかかります。これを高速に実行する方法。
数十億のレコードを含むテーブルがあり、条件なしで 1 つのフィールドを更新するだけで済みます。
update <table name> set flag='N'
これは私の更新クエリです。非常に長い時間がかかります。これを高速に実行する方法。
更新を実行するのにそれほど長く待つことができず、フラグを 'N' ではなく null のままにしておける場合は、これを非常に迅速に実行できます (テストされていませんが、動作するはずです) 。
alter table my_tab set unused column flag;
alter table my_tab add (flag char(1));
スペースを再利用したい場合は、後で未使用のチェックポイントをドロップできます (ドロップには時間がかかるため、これを行う場合は注意してください)。
それが役立つことを願っています
編集: この記事の@TTT のおかげで、明らかに 11g では、Oracle はすべての行に対して更新を実行するのではなく、デフォルト値をデータ ディクショナリに格納できます (以前の経験から予想していたこと)。これは、NULL の代わりに「N」値を使用できることを意味します。 NOT NULL とデフォルト値を必ず指定してください。
SQL> set timing on
SQL> drop table test1
Table dropped.
Elapsed: 00:00:00.23
SQL> create table test1
(
col1 varchar2(10),
flag char(1)
)
Table created.
Elapsed: 00:00:00.14
SQL> insert into test1
select 'x','Y'
from dual
connect by level <= 1000000
1000000 rows created.
Elapsed: 00:00:02.09
SQL> alter table test1 set unused column flag
Table altered.
Elapsed: 00:00:00.07
SQL> alter table test1 add (flag char(1) default 'N' not null )
Table altered.
Elapsed: 00:00:01.01
「NOT NULL」とデフォルトのみがないと、20 秒以上かかりました。この「fast=true」トリックは、null 以外とデフォルトを指定した場合にのみ機能します (これは本当に理にかなっています)。
最初のアイデア: スペースがある場合:
create table tmp_tab as select col1, ..., coln, "N" as flag
from your_tab;
rename table your_tab to your_tab_old;
rename tmp_tab to your_tab;
単純な更新と比較して非常に高速になります。
すべて問題がなければ、your_tab_oldを削除します。
2番目のアイデア:
update /*+parallel(your_tab 8)*/ your_tab set flag='N';
noparallelバージョンよりも高速になります。
更新しないでください。CTASを使用して、新しいテーブルの名前を変更します。
CREATE TABLE T_NEW NOLOGGING PARALLEL AS
SELECT COL1, COL2, 'N' FLAG FROM T_OLD;
次に、古いテーブルからインデックス、制約、または付与を適用します。このステップを忘れると、苦しむことになります。
DROP TABLE_T_OLD;
RENAME T_NEW TO T_OLD;
古いテーブルを削除するので注意してください。