我有一张非常大的桌子(5毫米的记录)。我正在尝试使用随机字母数字对表格的VARCHAR2列进行模糊处理。我的过程在较小的数据集上成功执行,但它最终会在我无法控制的设置的远程数据库上使用,所以我想批量执行UPDATE语句以避免耗尽undospace。
我可以启用某种选项,还是以块的形式进行更新的标准方法?
我将补充一点,没有被混淆的记录没有任何区别特征,所以我想在循环中使用rownum是行不通的(我认为)
答案 0 :(得分:5)
如果要更新表中的每一行,最好选择Create Table As Select,然后删除/截断原始表并使用新数据重新附加。如果您有分区选项,则可以将新表创建为具有单个分区的表,并将其与EXCHANGE PARTITION交换。
插入需要少量撤消,带有nologging的直接路径插入(/ + APPEND / hint)也不会产生太多重做。
使用任何一种机制,可能会有旧法价值的“法证”证据(例如,由于行移动而保留在撤消或分配给表格的“可用”空间中)。
答案 1 :(得分:2)
以下是未经测试的,但应该有效:
declare
l_fetchsize number := 10000;
cursor cur_getrows is
select rowid, random_function(my_column)
from my_table;
type rowid_tbl_type is table of urowid;
type my_column_tbl_type is table of my_table.my_column%type;
rowid_tbl rowid_tbl_type;
my_column_tbl my_column_tbl_type;
begin
open cur_getrows;
loop
fetch cur_getrows bulk collect
into rowid_tbl, my_column_tbl
limit l_fetchsize;
exit when rowid_tbl.count = 0;
forall i in rowid_tbl.first..rowid_tbl.last
update my_table
set my_column = my_column_tbl(i)
where rowid = rowid_tbl(i);
commit;
end loop;
close cur_getrows;
end;
/
这不是最佳效率 - 只需一次更新 - 但它会使用ROWID执行较小的用户可调节批量。
答案 2 :(得分:0)
我通过将主键映射到整数(mod n)来执行此操作,然后对每个x执行更新,其中0< = x< Ñ
例如,也许你不走运,主键是一个字符串。您可以使用自己喜欢的哈希函数对其进行哈希处理,并将其分为三个分区:
UPDATE myTable SET a=doMyUpdate(a) WHERE MOD(ORA_HASH(ID), 3)=0
UPDATE myTable SET a=doMyUpdate(a) WHERE MOD(ORA_HASH(ID), 3)=1
UPDATE myTable SET a=doMyUpdate(a) WHERE MOD(ORA_HASH(ID), 3)=2
您可能有更多分区,并且可能希望将其置于循环中(使用一些提交)。
答案 3 :(得分:0)
如果我必须更新数百万条记录,我可能会选择不更新。
我更可能创建一个临时表,然后从旧表中插入数据,因为插入不会占用大量的重做空间并且需要更少的撤消。
CREATE TABLE new_table as select <do the update "here"> from old_table;
index new_table
grant on new table
add constraints on new_table
etc on new_table
drop table old_table
rename new_table to old_table;
你可以使用并行查询来做到这一点,并且对大多数生成非常的操作都进行了nologging 小重做,根本没有撤消 - 只需要更新一小部分时间 数据。