我需要在oracle中更新一个巨大的表,其中包含约40 * 10 ^ 6个记录。 将要修改的行数大约为10 ^ 7。 确定要更新的行的查询很复杂,并且涉及联接。仅需30分钟即可识别将要更新的行的ID。
Select p.some_id from
(select some_id, col2,col3 from t1 where col2='someVulue' and col3 ='someValue') p
inner join (select some_id from t2 where t2.col3='someValue') q
on p.some_id=q.some_id
现在要进行更新,我需要添加另一个 join 或使用 IN 语句,这会使情况变得更糟。
有没有办法使这个并行化? 还是进行批量更新(每次更新25 * 10 ^ 4行)?有没有办法告诉oracle只更新前n行?然后n-> 2n,然后2n-> 3n ...?
该脚本将在生产环境中运行,因此无法重建表。
此更新包括将布尔列设置为true(如果有帮助的话)
答案 0 :(得分:3)
执行大规模更新的最快方法是使用并行DML,如下所示:
alter session enable parallel dml;
update /*+ parallel(16) */ some_table set some_column = 1;
commit;
有很多小陷阱需要提防。您需要拥有企业版。 UPDATE
将在表上获得排他锁,因此其他人将无法同时写入表。您的系统必须有足够的资源来支持大型UPDATE
,例如足够的重做,撤消,CPU,I / O和合理配置的系统。
(您可能希望将示例中的数字16更改为适合您的系统的数字。如果要最大程度地提高性能,但可能以其他进程为代价,请将数字设置为等于该数字的核心。)
Oracle并行性很棒,但是它并不是真正的优化。这使系统工作更加艰苦,而不是更加智能。在尝试并行处理之前,您可能需要查看UPDATE
中使用的SQL语句。您可能还想尝试使用MERGE
。 MERGE
语法起初有点棘手,但可以帮助避免重复联接,并允许散列联接,这种散列联接在更改大部分行时可以运行得更快。
答案 1 :(得分:0)
有几种方法。 1)将您的查询分成小块。 例如:通过主键拆分表或添加子句 2)如果您需要经常运行此程序,可以考虑使用分区表,然后并行运行更新 3)检查索引是否正确构建 顺便说一句,如果它不会对您的应用程序造成性能问题或阻止其他查询,那么我认为30分钟不是很长时间,这很正常。
答案 2 :(得分:0)
是否进行批量更新(每次更新25 * 10 ^ 4行)?有没有办法告诉oracle只更新前n行?然后n-> 2n,然后2n-> 3n,其中n为10
for loop i in 1..10
loop
update table1
set column_val=x
where rowid in (select rowid from table1
where rownum >= (((i-1) * (25*10^4))+1) and rownum <= i*(25*10^4)
);
end loop;