2

数十億のレコードを含むテーブルがあり、条件なしで 1 つのフィールドを更新するだけで済みます。

update <table name> set flag='N'これは私の更新クエリです。非常に長い時間がかかります。これを高速に実行する方法。

4

3 に答える 3

2

更新を実行するのにそれほど長く待つことができず、フラグを '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 以外とデフォルトを指定した場合にのみ機能します (これは本当に理にかなっています)。

于 2012-06-22T10:52:13.280 に答える
0

最初のアイデア: スペースがある場合:

  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バージョンよりも高速になります。

于 2012-06-22T10:44:15.880 に答える
0

更新しないでください。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;

古いテーブルを削除するので注意してください。

于 2012-06-22T10:42:29.930 に答える