Oracle UPDATE查询与RETURNING INTO子句相结合速度较慢

Oracle UPDATE查询与RETURNING INTO子句相结合速度较慢,oracle,oracle12c,Oracle,Oracle12c,我有一个更新查询,它返回更新的行ID。查询的执行时间约为90秒。当我删除Returning子句时,执行时间是1ms。 表更新\u表有39000行。 在这种情况下,查询更新0行。更新3行时-执行时间相同 DECLARE type intTable IS TABLE OF INTEGER; idCol intTable; BEGIN UPDATE update_table SET prop1 = 3, prop2 = NULL

我有一个更新查询,它返回更新的行ID。查询的执行时间约为90秒。当我删除Returning子句时,执行时间是1ms。 表更新\u表有39000行。 在这种情况下,查询更新0行。更新3行时-执行时间相同

DECLARE
  type intTable IS TABLE OF INTEGER;
  idCol intTable;
BEGIN
UPDATE 
  update_table
            SET  
            prop1 = 3, prop2 = NULL
            WHERE EXISTS (
                SELECT null FROM update_table f 
                    INNER JOIN rel_table1 u ON f.ID= u.ID
                    INNER JOIN rel_table2 VP ON f.another_ID = VP.another_ID
                WHERE (u.prop1 = 3) 
                    AND VP.prop1 = 1
                    AND (u.prop2 = 75)
                    AND f.ID = update_table.ID
            )
         ReTURNING ID BULK COLLECT INTO idCol;
.
.
.
  END;

为什么返回子句会减慢查询速度

我建议将其分为两部分,第一部分是
批量收集
,第二部分是
收集所有
的ID,两者都非常快,您可以继续从
idCol
中进一步引用更新的ID

DECLARE
  type intTable IS TABLE OF INTEGER;
  idCol intTable;
BEGIN
    SELECT f.id 
      BULK COLLECT INTO idCol
      FROM update_table f 
     INNER JOIN rel_table1 u ON f.ID= u.ID
     INNER JOIN rel_table2 VP ON f.another_ID = VP.another_ID
     WHERE (u.prop1 = 3) 
         AND VP.prop1 = 1
         AND (u.prop2 = 75);

    FORALL indx IN 1..idCol.COUNT
        UPDATE update_table
           SET prop1 = 3, prop2 = NULL
         WHERE id = idCol(indx);

.
.
.
END;

我希望我能帮忙

使用Oracle的一个很好的部分是知道什么是“应该”发生的,什么不是

添加
返回到
子句不会“假定”使更新运行得更慢。当发生了不应该发生的事情时,请查看Oracle的支持站点,看看这是否是一个已知的bug

在您的情况下,您似乎遇到了:

Bug 27131648-返回到的UPDATE语句上的次优计划

我不确定是否有补丁,但有一个简单的解决方法:使用
UNNEST
提示。在您的情况下,这将是:

UPDATE 
  update_table
            SET  
            prop1 = 3, prop2 = NULL
            WHERE EXISTS (
                SELECT /*+ UNNEST */ null FROM update_table f 
                    INNER JOIN rel_table1 u ON f.ID= u.ID
                    INNER JOIN rel_table2 VP ON f.another_ID = VP.another_ID
                WHERE (u.prop1 = 3) 
                    AND VP.prop1 = 1
                    AND (u.prop2 = 75)
                    AND f.ID = update_table.ID
            )
         ReTURNING ID BULK COLLECT INTO idCol;

这似乎是一个正确的答案。在添加
RETURNING
子句后,我可以观察到执行计划中的更改,其中包含一个带有嵌套子查询的
过滤器。
unest
提示用于将计划返回到以前的版本。