由於馬塞洛提示:
UPDATE mytable
SET new_column = <expr containing old_column>;
如果時間過長,未能因「快照太舊」錯誤(例如,如果表達式查詢另一種高活性表),如果爲新值列總是不爲NULL,您可以批量更新表:
UPDATE mytable
SET new_column = <expr containing old_column>
WHERE new_column IS NULL
AND ROWNUM <= 100000;
只需運行此語句,然後再運行它;沖洗,重複,直到它報告「0行更新」。這需要更長的時間,但每次更新都不太可能失敗。
編輯:
一個更好的選擇,應該是更有效的是使用DBMS_PARALLEL_EXECUTE
API。
示例代碼(從Oracle文檔):
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;
/
的Oracle文檔:https://docs.oracle.com/database/121/ARPLS/d_parallel_ex.htm#ARPLS67333
很少人後藤如果存在更新的/ instered列disabiling'INDEX' ES的極致,讓晚上的工作,對其進行分析。 – Guru 2010-04-14 07:50:51
我們需要更多信息。告訴我們關於表格模式......任何「計算」列?任何索引? 500k - 1m行不是很多記錄。 – Timothy 2010-04-14 08:46:19
謝謝大家的快速響應。我跳過了我正在使用生成的SQL語句的部分。現在我深入瞭解它,它看起來像生成的SQL逐行更新!因此,任何試圖以100個記錄塊分隔的嘗試都是沒有意義的......我將更改代碼以生成正確的SQL UPDATE語句,如同在接受的答案中一樣。 – 2010-04-14 09:35:50