Oracle试图更新列

时间:2012-06-22 09:32:27

标签: oracle

我有一个包含数十亿条记录的表,只需更新一个没有条件的字段。

update <table name> set flag='N'这是我的更新查询,需要很长时间。 如何让它快速执行。

3 个答案:

答案 0 :(得分:2)

如果确实无法等待那么长时间来运行更新,并且可以使用标志为空而不是“N”,那么您可以非常快速地执行此操作(未经测试,但应该可以正常工作) :

alter table my_tab set unused column flag;

alter table my_tab add (flag char(1));

如果你想要收回一些空间,你可以稍后放弃未使用的检查点(注意掉落需要一些时间,所以如果你选择这样做就要小心。)

希望有所帮助

编辑:感谢@TTT这个article,显然在11g中Oracle可以在数据字典中存储一个默认值,而不是对所有行执行更新(我以前的经验预期)。这意味着您可以使用“N”值而不是NULL。 只需确保指定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”技巧只有在指定not null和默认值时才有效(真的很有意义)。

答案 1 :(得分: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;

因为丢弃旧桌子所以要小心。

答案 2 :(得分: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。

第二个想法:

update /*+parallel(your_tab 8)*/ your_tab set flag='N';

将会    比noparallel版本快。