我有一个包含数十亿条记录的表,只需更新一个没有条件的字段。
update <table name> set flag='N'
这是我的更新查询,需要很长时间。
如何让它快速执行。
答案 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版本快。