我有更新查询,该查询返回更新的行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;
为什么返回子句会使查询变慢?
答案 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;
希望我能帮上忙!