【问题标题】:Oracle Bulk Collect and Update from cursor or user Update with Select subqueryOracle Bulk Collect and Update from cursor or user Update with Select 子查询
【发布时间】:2012-08-31 11:01:03
【问题描述】:

我有 2 个选项可以根据选择查询的游标更新表。

假设我有这个选择查询:

select id1 from table1

我的更新查询是:

update table2 set value=1 where table2.id2 = table1.id1

现在有两个选项:

  1. 为选择查询设置一个游标并批量获取它,然后在 for all 语句中触发更新查询。

  2. 使用 select 子查询编写更新查询:

    update table2 set value=1 where table2.id2 in (select id1 from table1)

哪个更好?

Oracle 是在内部将 select 子查询转换为批量收集还是将其视为普通游标?

【问题讨论】:

    标签: oracle oracle10g


    【解决方案1】:

    首先关于您的问题“Oracle 是否在内部将选择子查询转换为批量收集?”
    不,优化器计算一个计划并以某种适当的方式从子查询中选择数据。不涉及批量收集。

    对于您的问题“哪个更好?”。这要看情况。如果您可以制定一个查询,在一次运行中获取所有 table1.id1 并且 table2 有很多行,所以子选择是昂贵,那么我可能会使用批量收集。但请记住,根据数据量,您需要一些 PGA 来完成此操作。

    但我可能会指出另一个 - 恕我直言,非常优雅 - 解决方案:

    MERGE INTO table2
      USING (select id1 from table1)
       ON (id2 = id2)
      WHEN MATCHED THEN 
       UPDATE SET value=1
    ;
    

    这通常比执行子查询更快,也比批量收集更快:一次在 table1 上运行,一次在 table2 上运行。 (根据您的需要添加where 子句)

    【讨论】:

    • “首先你的问题是“Oracle 是否在内部将选择子查询转换为批量收集?”没有。老实说,这是不正确的。尝试使用 dbms_profiler FOR rec IN select ,您会看到隐式批量大约有 5 行:)
    • @AlexanderTokarev:我不明白你的意思。 FOR rec IN select 显然会为 FOR 循环进行批量收集。问题在update table2 set value=1 where table2.id2 in (select id1 from table1) 上,不涉及批量收集。 PL/SQL FOR .. LOOP 不是子查询。
    • 我明白你的意思。有点困惑 :) 错过了 SUBQUERY 词 :)
    • 谢谢@GWu - 我会试试看。
    • @AlexanderTokarev - 我们是否有一些关于由 Oracle 自动将普通游标转换为批量收集 5 的文档。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多