Oracle - 案例花费很长时间后更新

时间:2017-06-22 09:09:17

标签: sql oracle performance query-optimization

我有一个包含以下列的表:

val      range_from      range_to    final_val
-2.12    -2                  2               -2
-0.12    -2                  2               -0.12
-0.12    -2                  2               -0.12
1.51     -2                  2               1.51
-1.29    -2                  2               -1.29
2.23     -2                  2               2

final_val是我需要使用以下条件计算的东西:

update table1
SET final_val= case
when val > range_to then range_to
when val < range_from then range_from
else VAL
END;

我的表格定义:

Name       Null Type   
---------- ---- ------ 
VAL             NUMBER 
RANGE_FROM      NUMBER 
RANGE_TO        NUMBER 
FINAL_VAL       NUMBER 

我桌上没有任何索引

以上查询需要很长时间才能执行。表大小为30GB。执行它需要超过16个小时。

有没有更好的方法来完成这项工作?

3 个答案:

答案 0 :(得分:0)

尝试

update table1 SET final_val = val where val between range_from and range_to;
update table1 SET final_val = range_from where val < range_from;
update table1 SET final_val = range_to where val > range_to;

答案 1 :(得分:0)

  1. 首先,您应该查看索引和约束。如果有的话,最好暂时删除它们并在更新后将其恢复。
  2. 有时,基于select创建临时表比更新表更快。你可以尝试一下。

答案 2 :(得分:0)

您正在更新表中的每条记录,并且Oracle确实遵守,即使不更改final_val值,记录也会更新。因此,第一个措施是仅更新必须更新的记录,例如:

UPDATE table1
SET final_val = case when val > range_to then range_to 
                     when val < range_from then range_from 
                     else val 
                end
WHERE final_val <> case when val > range_to then range_to 
                        when val < range_from then range_from 
                        else val
                   end;

(如果列可以为空,则可能需要进行调整。例如:WHERE DECODE(final_val, case when ... end, 'equal', 'different') = 'different'。)

然后你可以拥有一台可以执行并行操作的机器。所以提示可能有用:

UPDATE /*+parallel(table1,8)*/ table1
SET final_val = case when val > range_to then range_to 
                     when val < range_from then range_from 
                     else val 
                end
WHERE final_val <> case when val > range_to then range_to 
                        when val < range_from then range_from 
                        else val
                   end;

但是,您似乎希望final_val始终是valrange_fromrange_to计算的值。在那种情况下,为什么要更新?写一个视图或使用虚拟列。