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

Oracle SQL-如何更高效、更快地进行大规模更新?,sql,oracle,updates,updating,Sql,Oracle,Updates,Updating,我正在尝试一次更新50万行。我有一张桌子,上面摆着这样的产品: +------------+----------------+--------------+-------+ | PRODUCT_ID | SUB_PRODUCT_ID | DESCRIPTION | CLASS | +------------+----------------+--------------+-------+ | A001 | ACC1 | coffeemaker | A

我正在尝试一次更新50万行。我有一张桌子,上面摆着这样的产品:

+------------+----------------+--------------+-------+ | PRODUCT_ID | SUB_PRODUCT_ID | DESCRIPTION | CLASS | +------------+----------------+--------------+-------+ | A001 | ACC1 | coffeemaker | A | | A002 | ACC1 | toaster | A | | A003 | ACC2 | coffee table | A | | A004 | ACC5 | couch | A | +------------+----------------+--------------+-------+ 我正在做一个查询,将一个update语句放在另一个update语句的下面,并将commit语句放在每1000行的下面。 它工作很好(缓慢,但很好),但我想做得更好,如果它可以在任何方式


有一种更好的方法可以更高效、更快地完成此操作?

一种方法是创建一个临时表来保存更新信息:

新产品类别

product_id  class
==========  =====
A           A001
B           A005
Z           A150
product\u id
应该是此新表上的索引主键。然后,您可以对连接到此临时表的旧表执行
更新
合并

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


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

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

新产品类别

product_id  class
==========  =====
A           A001
B           A005
Z           A150
product\u id
应该是此新表上的索引主键。然后,您可以对连接到此临时表的旧表执行
更新
合并

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


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

除非您有索引,否则每个更新语句都会扫描整个表。即使您确实有索引,编译和执行每个语句也会带来成本

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

如果条件的数量相对有限(如您的示例所示),并且它们不会经常更改,那么您也可以将其作为一个简单的案例:

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')
如果您的
字段可能已经设置为正确的值,那么添加一个条件以确保您没有将某些内容更新为相同的值也是很有价值的。例如,如果:

update products set class = 'A' where product_id = 'A001';
更新5000条记录,其中4000条已设置为“A”,那么这将大大提高效率:

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

除非有索引,否则每个update语句都会扫描整个表。即使您确实有索引,编译和执行每个语句也会带来成本

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

如果条件的数量相对有限(如您的示例所示),并且它们不会经常更改,那么您也可以将其作为一个简单的案例:

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')
如果您的
字段可能已经设置为正确的值,那么添加一个条件以确保您没有将某些内容更新为相同的值也是很有价值的。例如,如果:

update products set class = 'A' where product_id = 'A001';
更新5000条记录,其中4000条已设置为“A”,那么这将大大提高效率:

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

表中总共有多少行?你有什么索引?它们(表和索引)是分区的吗?表和索引上的统计数据是最新的吗?桌子上的主键是什么?嗨@Vampiro!表中总共有多少行?大约980.000您有哪些索引?产品标识(is PK)和子产品标识(表和索引)是否已分区?表和索引上的统计数据是最新的吗?我相信,但我不太清楚(很抱歉这个答案)。我真的不管理这个表,我只能在上面做DML语句。表上的主键是什么?产品ID您的
update
语句的数据来自哪里?新的
值似乎存储在SQL语句文件之外的其他位置。如果它们在表中,则需要执行基于单个集合的相关更新。如果它们位于一个文件中,则您希望加载该文件(可能通过外部表),并执行单个基于集合的相关更新。当您修改大量数据(超过50%)时,最好避免单独更新。看看是否可以重写逻辑来批量更新。另外,将滑车和索引作为散列分区进行分区,这肯定会有帮助。您对“更好”的标准是什么?你想要更快还是更高效?(它们不是一回事)桌子的结构是什么?你的计划在哪里?表中有多少条记录?它是如何编制索引的?您需要并发操作吗?表中总共有多少行?你有什么索引?它们(表和索引)是分区的吗?表和索引上的统计数据是最新的吗?桌子上的主键是什么?嗨@Vampiro!表中总共有多少行?大约980.000您有哪些索引?产品标识(is PK)和子产品标识(表和索引)是否已分区?表和索引上的统计数据是最新的吗?我相信,但我不太清楚(很抱歉这个答案)。我真的不管理这个表,我只能在上面做DML语句。表上的主键是什么?产品ID您的
update
语句的数据来自哪里?新的
值似乎存储在SQL语句文件之外的其他位置。如果它们在表中,则需要执行基于单个集合的相关更新。如果它们在一个文件中,则可能需要通过一个外部表加载该文件,并基于单个集合执行相关操作