Oracle SQL - 如何更高效,更快速地进行大规模更新?

时间:2016-01-24 23:45:32

标签: sql oracle updates updating

我试图一次更新500.000行。我有一张桌子,上面有这样的产品:

+------------+----------------+--------------+-------+
| PRODUCT_ID | SUB_PRODUCT_ID | DESCRIPTION  | CLASS |
+------------+----------------+--------------+-------+
| A001       | ACC1           | coffeemaker  | A     |
| A002       | ACC1           | toaster      | A     |
| A003       | ACC2           | coffee table | A     |
| A004       | ACC5           | couch        | A     |
+------------+----------------+--------------+-------+

我有各自的个别陈述,例如:

UITableViewRowAction

我正在进行查询,将一个更新语句放在另一个更新语句下面,并将每个1.000行放入一个commit语句。 它工作正常(慢,但很好),但如果它可以以任何方式可行,我想做得更好。

有更好的方法来提高效率和速度吗?

2 个答案:

答案 0 :(得分:1)

一种方法是创建一个包含更新信息的临时表:

<强> new_product_class

product_id  class
==========  =====
A           A001
B           A005
Z           A150

product_id应该是此新表的索引主键。然后,您可以在加入此临时表的旧表上执行UPDATEMERGE

UPDATE (SELECT p.product_id, p.class, n.product_id, n.class
          FROM product p
          JOIN new_product_class n ON (p.product_id = n.product_id)
  SET p.class = n.class

MERGE INTO product p
  USING new_product_class n
  ON (p.product_id = n.product_id)
  WHEN MATCHED THEN
      UPDATE SET p.class = n.class

合并应该很快。您可以根据您的环境调查的其他事项:使用nologging创建一个基于旧表的新表,然后重命名(应该在之前和之后备份),批量更新。

答案 1 :(得分:1)

除非您有索引,否则每个更新语句都会扫描整个表。即使您有索引,也会产生与每个语句的编译和执行相关的成本。

如果您有很多条件,并且这些条件可能会有所不同,那么我认为Glenn的解决方案显然是可行的方法。这可以在单个事务中完成所有操作,并且没有理由运行1,000行的批处理 - 只需一次完成所有操作。

如果条件的数量相对有限(作为你的例子),并且它们不经常变化,那么你也可以这样做:

update products
set class =
  case product_id
    when 'A001' then 'A'
    when 'A005' then 'B'
    when 'A150' then 'C'
  end
where
  product_id in ('A001', 'A005', 'A150')

如果可能您的class字段已设置为正确的值,那么添加条件以确保您没有将某些内容更新为相同值也很有价值。例如,如果:

update products set class = 'A' where product_id = 'A001';

更新了5,000条记录,其中4,000条记录已经设置为“A&#39;”,这将显着提高效率:

update products
set class = 'A'
where
  product_id = 'A001' and
 (class is null or class != 'A')