DECLARE
l_sql_stmt VARCHAR2(1000);
l_try NUMBER;
l_status NUMBER;
BEGIN
-- Create the TASK
DBMS_PARALLEL_EXECUTE.CREATE_TASK ('mytask');
-- Chunk the table by ROWID
DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_ROWID('mytask', 'HR', 'EMPLOYEES', true, 100);
-- Execute the DML in parallel
l_sql_stmt := 'update EMPLOYEES e
SET e.salary = e.salary + 10
WHERE rowid BETWEEN :start_id AND :end_id';
DBMS_PARALLEL_EXECUTE.RUN_TASK('mytask', l_sql_stmt, DBMS_SQL.NATIVE,
parallel_level => 10);
-- If there is an error, RESUME it for at most 2 times.
l_try := 0;
l_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS('mytask');
WHILE(l_try < 2 and l_status != DBMS_PARALLEL_EXECUTE.FINISHED)
LOOP
l_try := l_try + 1;
DBMS_PARALLEL_EXECUTE.RESUME_TASK('mytask');
l_status := DBMS_PARALLEL_EXECUTE.TASK_STATUS('mytask');
END LOOP;
-- Done with processing; drop the task
DBMS_PARALLEL_EXECUTE.DROP_TASK('mytask');
END;
/
create table new_table as table orig_table with data;
update new_table set column = <expr>
start transaction;
drop table orig_table;
rename new_table to orig_table;
commit;
7条答案
按热度按时间66bbxpm51#
通常的方法是使用UPDATE:
你应该可以做到这是一个单一的交易。
91zkwejq2#
正如马塞洛所说:
如果此操作花费的时间太长,并且由于"快照太旧"错误而失败(例如,如果表达式查询另一个高度活跃的表),并且如果列的新值始终为NOT NULL,则可以成批更新表:
只需运行此语句COMMIT,然后再次运行它;冲洗,重复,直到它报告"0行更新"。这将需要更长的时间,但每次更新不太可能失败。
一个更好、效率更高的替代方法是使用
DBMS_PARALLEL_EXECUTE
API。示例代码(来自Oracle文档):
Oracle文档:www.example.comhttps://docs.oracle.com/database/121/ARPLS/d_parallel_ex.htm#ARPLS67333
rt4zxlrg3#
您可以删除表上的任何索引,然后执行插入,再重新创建索引。
w6lpcovy4#
可能对你不起作用,但这是我过去在类似情况下用过几次的技巧。
创建了updated_{table_name},然后选择批量插入到此表中。完成后,这取决于Oracle(我不知道也不使用)是否支持以原子方式重命名表的功能。updated_{table_name}将变为{table_name},而{table_name}将变为original_{table_name}。
上一次我不得不这样做是为了一个有几百万行的索引很重的表,在对它进行一些重大更改所需的持续时间内,绝对不能锁定它。
esyap4oy5#
数据库版本是什么?查看11g中的虚拟列:
添加具有默认值http://www.oracle.com/technology/pub/articles/oracle-database-11g-top-features/11g-schemamanagement.html的列
wydwbb8l6#
更新酒店设置折扣=30,其中酒店ID〉= 1且酒店ID〈= 5504
xuo3flqw7#
对于Postgresql,我做了类似这样的事情(如果我们确定没有更多的更新/插入发生):
更新: