我必须更新包含数百万行的表。更新非常简单,但由于它会修改数百万条记录,我想知道什么是最佳解决方案:
我会选择第一个解决方案但是同事建议我分批进行,这样就不会阻止访问该表的其他会话。
那么哪种解决方案更好?
谢谢,
答案 0 :(得分:1)
如果您的数据库有停机时间,那么最快的解决方案可能就像Tom Kyte所说:
create table new as select ... from old;
drop table old;
rename table new to old;
如果您没有窗口可以发生这种情况(可能会快几个数量级)并且阻止该表是不允许的,那么我建议您查看dbms_parallel_execute。 Oracle可以将表拆分为块并分别更新每个块。它比批量收集和更新forall更清洁,因为如果你想要一个具有附加条件and rowid between :start and :stop
的大更新,你可以使用更新语句
begin
dbms_parallel_execute.create_task ( task_name => 'MyTask');
dbms_parallel_execute.create_chunks_by_rowid(
task_name => 'MyTask',
table_owner => 'Me',
table_name => 'MyTable',
by_row => true,
chunk_size => 1000);
dbms_parallel_execute.run_task(
task_name => 'MyTask',
sql_stmt => 'UPDATE mytable
set col = newval
where ...
and rowid between :start_id and :end_id',
language_flag => dbms_sql.native,
parallel_level => 8);
然后,一旦完成,你检查状态:
dbms_parallel_execute.task_status(task_name => 'MyTask') = dbms_parallel_execute.FINISHED
如果成功,则删除任务。
dbms_parallel_execute.drop_task(task_name => 'MyTask');
答案 1 :(得分:0)
花费大量时间处理INSERT,UPDATE或DELETE语句或循环查询结果的程序。您将需要调查用于发出DML的FORALL语句,以及用于查询的BULK COLLECT INTO和RETURNING BULK COLLECT INTO子句。您可以查看此文档以用于您的目的。 http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/tuning.htm
这里有你的情况答案。
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:6407993912330