m_p*_*tor 34 sql oracle performance
我有一张包含大量记录的表(可能超过500 000或1 000 000).我在此表中添加了一个新列,我需要使用此表中另一列的相应行值为列中的每一行填充一个值.
我尝试使用单独的事务来选择100个记录的每个下一个块并更新它们的值,但是这仍然需要几个小时才能更新Oracle10中的所有记录.
在SQL中执行此操作的最有效方法是什么,而不使用某些特定于方言的功能,因此它可以在任何地方使用(Oracle,MSSQL,MySQL,PostGre等)?
附加信息:没有计算字段.有索引.使用生成的SQL语句逐行更新表.
Mar*_*tos 53
通常的方法是使用UPDATE:
UPDATE mytable
SET new_column = <expr containing old_column>
Run Code Online (Sandbox Code Playgroud)
您应该能够做到这一点是一个单一的交易.
正如马塞洛所说:
UPDATE mytable
SET new_column = <expr containing old_column>;
Run Code Online (Sandbox Code Playgroud)
如果由于"快照太旧"错误而花费太长时间并且失败(例如,如果表达式查询另一个高活动表),并且列的新值始终为NOT NULL,则可以批量更新表:
UPDATE mytable
SET new_column = <expr containing old_column>
WHERE new_column IS NULL
AND ROWNUM <= 100000;
Run Code Online (Sandbox Code Playgroud)
只需运行此语句COMMIT,然后再次运行它; 冲洗,重复直到报告"0行更新".它需要更长的时间,但每次更新都不太可能失败.
编辑:
更有效的替代方案是使用DBMS_PARALLEL_EXECUTEAPI.
示例代码(来自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;
/
Run Code Online (Sandbox Code Playgroud)
Oracle Docs:https://docs.oracle.com/database/121/ARPLS/d_parallel_ex.htm#ARPLS67333
| 归档时间: |
|
| 查看次数: |
89283 次 |
| 最近记录: |