如何在oracle pl/sql中批量更新大型表,以避免耗尽空间?

如何在oracle pl/sql中批量更新大型表,以避免耗尽空间?,oracle,plsql,Oracle,Plsql,我有一张很大的桌子。我试图用随机字母数字混淆表中每个记录的VARCHAR2列。我的过程在较小的数据集上成功执行,但它最终将在我无法控制其设置的远程数据库上使用,因此我希望成批执行UPDATE语句以避免耗尽空间 是否有某种我可以启用的选项,或者一种标准的方法来进行分块更新 我要补充的是,记录中没有任何未被混淆的显著特征,因此我认为在循环中使用rownum的想法是行不通的。我通过将主键映射到整数mod n来实现这一点,然后对每个x执行更新,其中0如果要更新表中的每一行,最好按照Select创建一个表

我有一张很大的桌子。我试图用随机字母数字混淆表中每个记录的VARCHAR2列。我的过程在较小的数据集上成功执行,但它最终将在我无法控制其设置的远程数据库上使用,因此我希望成批执行UPDATE语句以避免耗尽空间

是否有某种我可以启用的选项,或者一种标准的方法来进行分块更新


我要补充的是,记录中没有任何未被混淆的显著特征,因此我认为在循环中使用rownum的想法是行不通的。

我通过将主键映射到整数mod n来实现这一点,然后对每个x执行更新,其中0如果要更新表中的每一行,最好按照Select创建一个表,然后删除/截断原始表并用新数据重新追加。如果您有分区选项,那么可以将新表创建为具有单个分区的表,并简单地将其与EXCHANGE分区交换

插入所需的撤消操作要少得多,使用NOLOGING/+APPEND/hint的直接路径插入也不会产生太多的重做操作


无论采用哪种机制,都可能存在旧值的“取证”证据,例如由于行移动而保留在撤消中或分配给表的可用空间中。

以下内容未经测试,但应有效:

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进行更小的、用户可调的批处理。

如果我必须更新数百万条记录,我可能会选择不更新

我更可能创建一个临时表,然后从旧表中插入数据,因为insert不会占用大量的重做空间,而且执行的撤消操作更少

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;
您可以使用并行查询来实现这一点,不记录大多数操作会生成非常复杂的结果 几乎不需要重做,也不需要撤消—只需更新数据库所需时间的一小部分
数据

如果想要大小不同的集合,应该使用NTILE分析函数;ORA_散列可能具有不可预测的值,尤其是当使用的值不是要散列到的存储桶数的2次方时。ORA_HASHn,3可以有4个值,所以您的示例可能会错过更新大约1/4的数据。Adam:请注意,我使用的是MODORA_HASHID,3,而不是ORA_HASHID,3。我故意使用MOD,因为ORA_散列的额外参数令人困惑。谢谢你的推荐。我还不完全熟悉分析。@adam musch:试图在WHERE中使用NTILE给了我一个错误:ORA-30483:不允许使用窗口函数here@Greg,则必须嵌套查询,就像where子句中使用的所有分析函数一样。请参见此处-别忘了禁用引用表的外键约束。似乎此查询的相同答案可能仍然会生成太旧的ORA-01555快照。可能是因为在提交之间进行抓取
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;