如何为oracle循环查询生成执行计划,如下所示:
BEGIN
FOR L IN (SELECT FIRST_NAME, LAST_NAME, SOME_ID FROM TABLE1)
LOOP
INSERT INTO TABLE2 (FIRSTNAME, LASTNAME)
(SELECT FNAME, LASTNAME FROM TABLE2 WHERE SOME_ID = L.SOME_ID)
V_CNT := V_CNT + 1;
IF (MOD(V_CNT, 1000)=0) THEN
COMMIT;
END IF;
END LOOP;
如何为上面的块生成执行计划?
我问了类似的问题earlier并决定从我的存储过程中提取块并为单独生成执行计划。虽然我知道如何为简单查询生成计划,但我不知道如何为上面的循环块生成它们。
答案 0 :(得分:3)
您的PL / SQL块可以在SQL中重写:
INSERT INTO table2 (firstname, lastname)
SELECT fname, lastname
FROM table2
WHERE some_id IN (SELECT some_id FROM table1);
然后你可以“解释计划”上面的INSERT。
如果你必须进行批量提交,那么使用BULK COLLECT ... LIMIT和FORALL比循环游标更有效,特别是如果你正在处理数百万行。有用的链接:
答案 1 :(得分:1)
您无法为PL/SQL
块生成执行计划,仅用于查询。
执行计划显示了声明式命令(SQL
)如何在引擎盖下执行,i。即使用什么程序。它将声明性构造(集合操作)转换为过程(嵌套循环,散列连接,排序等)。
PL/SQL
,顾名思义,是一种过程语言,定义了执行计划本身 - 在你的案例中嵌套循环。
如果您想查看内部查询的执行计划,则应复制它并发出EXPLAIN PLAN FOR …
请注意,这可以更有效地重写为:
BEGIN
FOR L IN
(
SELECT MIN(some_id) AS minid, MAX(some_id) AS maxid
FROM (
SELECT some_id, rownum AS rn
FROM (
SELECT some_id
FROM table1
ORDER BY
some_id
)
)
GROUP BY
TRUNC(rn / 1000)
)
LOOP
INSERT
INTO TABLE2 (FIRSTNAME, LASTNAME)
SELECT FNAME, LASTNAME
FROM table1
JOIN table2
ON table2.some_id = table1.some_id
WHERE table1.some_id BETWEEN l.minid AND l.maxid
V_CNT := V_CNT + 1;
IF (MOD(V_CNT, 1000)=0) THEN
COMMIT;
END IF;
END LOOP;
END;
答案 2 :(得分:1)
如果您对程序PL / SQL代码的性能感兴趣,可能需要调查PL / SQL分析。
Profiler允许您收集有关PL / SQL的运行时性能的信息。分析运行完成后,您可以报告结果并查看每行执行次数的信息,每行的平均执行时间。这可以帮助您识别瓶颈,并指出您可能需要调整注意力的第一件事。
您最大的潜在回报是查看性能最差的代码并使其运行得更好。一旦改进,再次进行配置以验证您的改进并找到可能需要注意的下一个声明。
这里有一个很好的第一个介绍:Oracle's DBMS Profiler