从Oracle中非常大的记录集中选择记录子集会耗尽内存

Cyn*_*ech 3 sql oracle oracle10g

我有一个流程将日期从GMT转换为澳大利亚东部标准时间.为此,我需要从数据库中选择记录,处理它们然后再保存.

要选择记录,我有以下查询:

SELECT id,
  user_id,
  event_date,
  event,
  resource_id,
  resource_name
FROM
  (SELECT rowid id,
    rownum r,
    user_id,
    event_date,
    event,
    resource_id,
    resource_name
  FROM user_activity
  ORDER BY rowid)
WHERE r BETWEEN 0 AND 50000
Run Code Online (Sandbox Code Playgroud)

从总共大约中选择一个50000行的块.6000万行.我将它们分开是因为a)Java(写入更新过程的内容)耗尽了很多行的内存(每行都有一个bean对象)和b)我只有4 gig的Oracle临时空间可以播放用.

在这个过程中,我使用rowid来更新记录(所以我有一个唯一的值)和rownum来选择块.然后我在迭代中调用此查询,选择接下来的50000条记录,直到没有剩余(java程序控制它).

我得到的问题是,我仍然在使用此查询耗尽Oracle临时空间.我的DBA告诉我,不能授予更多临时空间,因此必须找到另一种方法.

我已经尝试用子视图替换子查询(我认为使用带排序的所有临时空间),但是使用视图的解释计划与原始查询之一相同.

是否有不同/更好的方法来实现这一点而不会遇到内存/温度空间问题?我假设更新查询更新日期(而不是java程序)会遇到使用临时空间可用的相同问题?

非常感谢您对此的帮助.

更新

我按照下面的建议走了pl/sql块的路径:

declare
  cursor c is select event_date from user_activity for update;
begin
  for t_row in c loop
    update user_activity
      set event_date = t_row.event_date + 10/24 where current of c;
    commit;
  end loop;
end;
Run Code Online (Sandbox Code Playgroud)

但是,我的撤消空间已经用完了.我的印象是,如果在每次更新后进行提交,则对撤消空间的需求很小.这个假设我不正确吗?

Jon*_*ler 6

单个更新可能不会遇到同样的问题,并且可能会快几个数量级.由于排序,只需要大量的临时表空间.虽然如果您的DBA对临时表空间如此吝啬,您可能最终会耗尽UNDO空间或其他内容.(看看ALL_SEGMENTS,你的桌子有多大?)

但是如果你真的必须使用这种方法,也许你可以使用过滤器而不是命令.创建1200个桶并一次处理一个:

where ora_hash(rowid, 1200) = 1
where ora_hash(rowid, 1200) = 2
...
Run Code Online (Sandbox Code Playgroud)

但这将是可怕的,非常缓慢.如果价值在整个过程中途发生变化,会发生什么?单个SQL语句几乎肯定是执行此操作的最佳方式.