表锁会加速Oracle 10g企业中的更新语句吗?

时间:2011-03-30 13:09:45

标签: sql performance oracle oracle10g

我们有一个相当宽的BaseData表,其中有大约3300万行。然后我们有一个更新查询,它将其连接到包含各种参数的其他几个表,应用了一些函数,按原始Id存在一个组,然后将结果写回几列中的BaseData表。

这个过程很慢,所以我正在研究加速它的方法。我在SQLServer中拥有大部分经验,所以这种类型的Oracle内部我还不知道。

我怀疑的一件事是,在更新期间,Oracle会创建每一行的版本,因此任何其他读者都可以读取未受影响的行。然而,这需要相当多的资源。有没有办法让更新对表执行写锁定,这样就不会创建每一行的版本?

你们有大量更新的其他提示吗?我们已经把它分成几批了。每个批处理都在表的单独分区中,然后并行运行多个更新。但它仍然太慢了。

3 个答案:

答案 0 :(得分:3)

简短的回答是,在Oracle中,对表进行独占锁定不会阻止其他会话读取它,或者不得不承担生成读取一致数据视图的工作。同样,在Oracle中,您无法告诉会话启用“脏读”。

嗯,第一个问题是什么是缓慢的 - 是加入和应用函数的所有工作,还是写回来的?与更新语句相比,SELECT my_updated_resultset FROM BASEDATA JOIN...的执行情况如何?您是否验证过BaseData的读者与更新过程之间存在争用?此外,它对业务来说太慢了,或者只是比你想象的要慢?

要考虑的另一个选择是使用分区交换来执行更新。高级概念将是:

  1. CREATE TABLE BASEDATA_XCHG as SELECT * FROM BASEDATA WHERE 1 = 0;
  2. INSERT /*+ append */ INTO BASEDATA_XCHG SELECT my_updated_resultset FROM BASEDATA PARTITION (ONLY_ONE_PARTITION) JOIN...
  3. 在BASEDATA_XCHG表上创建所有必需的索引和约束。
  4. ALTER TABLE BASEDATA EXCHANGE PARTITION (ONLY_ONE_PARTITION) WITH BASEDATA_XCHG
  5. 如果要更新BASEDATA表分区中的大多数行,请不要更新它们 - 创建一个新表并将其交换出来。蒂姆戈尔曼有一篇名为"Scaling to Infinity"的优秀论文,更深入地涵盖了这一概念;你可以查看一下。

答案 1 :(得分:3)

除了亚当的回答:

在更新语句上运行EXPLAIN PLAN并检查执行计划。

有可能添加索引来支持你的连接和WHERE条件可以加速查询。

答案 2 :(得分:1)

Oracle使用还原段来实现读取一致性(与SCN一起使用,阅读更多here

我假设这些大型批处理进程正在暂存区域运行,而不是许多不同进程正在使用的“prod”实例。如果要更新某个大表的25%或更多(粗略数字),那么执行CTAS(创建表作为select ...)可能比尝试更新更好。您的CTAS将包含新表的更新逻辑。完成后,在新表上添加索引/授权/等,并将new重命名为old。您还可以在CTAS上添加并行提示和nologging,以进一步提高速度。