我想知道以最有效的方式针对单个列更新超大型Oracle表中的每一行。例如:
update mytable set mycolumn=null;
要么:
update mytable set mycolumn=42;
我的知识可能很过时。我要做的是更改表以删除列。然后,我更改表以添加具有我要使用的新值的默认值的列。然后,我更改表以删除该列的默认值。我发现这比运行更新要快得多,但是我觉得有更好的方法。
我想知道以最有效的方式针对单个列更新超大型Oracle表中的每一行。例如:
update mytable set mycolumn=null;
要么:
update mytable set mycolumn=42;
我的知识可能很过时。我要做的是更改表以删除列。然后,我更改表以添加具有我要使用的新值的默认值的列。然后,我更改表以删除该列的默认值。我发现这比运行更新要快得多,但是我觉得有更好的方法。
Answers:
在进行此批量更新时,很大程度上取决于针对此表进行的其他活动。我希望您拥有某种测试环境,可以在其中运行您想做的事的一些样本,并了解哪种方法最好。我会尝试:
update table set column_name = blah
;updating the column=blah
并提交每个X更新(也许是10000)。您可以通过复制代码并使它复制成为并行的主键的单独部分来并行化此代码。对于在OLTP系统中非常活跃使用的表,我们有一个非常相似的问题,我们能够对其进行5倍并行化,并且在没有用户锁定的情况下对每10000次提交的100+ MM行表没有用户锁定的影响。您没有说如何您的表太大或正在运行哪种应用程序,但是这种解决方案可能适合您。
快速而言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
我在这里重复pappes的答案以供参考。(请注意,此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;
如果没有空间限制,则可以创建一个新表,该表与添加了新列的表相同,然后删除旧表:
create new_table as
select old_table.*, (with or without default_Value) as new_column
from old_table;
尝试多个更新/提交序列。在没有提交的情况下插入/更新/删除太多的行会导致大量的IO负载。知道块大小,记录大小和内容,可以进行相当优化。
对于删除表上的整个数据,truncate table x
它比更好delete from x
。清除也会增加另一个过程的工作量。
编辑:您可以使用inmemory
选项,以列格式将表加载到内存中,然后进行更新。它确实取决于数据库的关系和结构。看到这篇文章。
truncate
或delete
将是任何帮助。