Oracle 更新非索引和非分区表的有效方法?
Posted
技术标签:
【中文标题】Oracle 更新非索引和非分区表的有效方法?【英文标题】:Oracle efficient way of updating non-indexed and non-partioned table? 【发布时间】:2020-03-04 10:05:20 【问题描述】:有没有一种有效的方法来更新没有索引和分区(大约 5000 万行)的表的行?
我有一个日期字段 LOAD_DTTM 和该字段的值,用于需要更新的行(大约 2000 个不同的日期)。
如果我在 WHERE 子句中指定日期以及行的 UNIQUE_ID,更新会更快吗?
【问题讨论】:
不,你注定要扫描整个表来寻找你需要更新的行。这就是发明索引的原因! @Mari 。 . .你的问题不清楚。您需要更新所有行吗?还是只是一小部分? 我已经重建了那个表,创建了索引和分区。这是最好的选择,感谢您的帮助:) 【参考方案1】:如果您想更新所有或大量行,那么最快的方法是:
create table my_table_copy as
select ... -- all the columns, updating values as required
from my_table;
drop table my_table;
rename my_table_copy to my_table;
如果您的表有任何索引、约束或触发器,您现在需要重新添加它们 - 但您似乎没有这个问题!
【讨论】:
【参考方案2】:您可以创建一个 PL/SQL 过程,该过程每隔 n 行计数循环、更新和提交表——比如每 20.000 行。我不建议更新整个表,因为它会在很长一段时间内创建一个锁,并在外部因素的情况下使您面临数据丢失。
【讨论】:
您所描述的将是性能杀手,并且在循环内提交时,将非常容易受到 ora-1555 的影响。 “逐行”处理意味着“逐行”处理。【参考方案3】:答案是否。 即使您按照您的说明在 WHERE 子句中指定了这两个条件,也无法帮助您避免对表进行全面扫描。 即使您的条件之一将唯一标识该行,它仍然无济于事。
在 Oracle 12C ver.2 上测试了一个与您的案例类似的真实示例。没有索引,没有分区,什么都没有。只是简单的 4 列表格
我有一个包含 1800 万条记录的表。 我也有 CUSTOMER_ID,它是一行的唯一标识符。 我那里也有 ORDER_DATE 列。
即使我做了你提到的查询
update hit set status = 1 where customer_id = 408518625844 and order_date = '09-DEC-19';
避免全表扫描对我没有帮助。请参阅下面的执行计划。因此,在您指定的条件下,您将始终获得可能的最慢执行时间。对 5000 万行进行全表扫描实际上是最坏的情况。
并注意该成本,它是 1800 万行上的 26539。 因此,如果您有 5000 万行,我们可以轻松地为您的查询带来更多成本
【讨论】:
以上是关于Oracle 更新非索引和非分区表的有效方法?的主要内容,如果未能解决你的问题,请参考以下文章