结合RETURNING INTO子句

时间:2019-02-08 09:40:08

标签: oracle oracle12c

我有更新查询,该查询返回更新的行ID。查询的执行时间约为90秒。当我删除Returning子句时,执行时间为1ms。 表update_table具有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;

为什么返回子句会使查询变慢?

2 个答案:

答案 0 :(得分:3)

使用Oracle的很大一部分就是知道发生了什么“假设”而没有发生什么。

未“添加” RETURNING INTO子句以使更新运行更慢。如果发生了不希望发生的事情,请检查Oracle支持站点以查看它是否是已知错误。

以您的情况来说,您似乎遇到了:

  

错误27131648-具有返回状态的更新语句的子优化计划

我不确定是否有补丁,但是有一个简单的解决方法:使用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;

答案 1 :(得分:1)

我建议将其分为两部分,第一部分BULK COLLECT和第二部分FORALL,它们都非常快,而且您将能够继续从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;

希望我能帮上忙!