How can I generate execution plan for an oracle loop query like below:
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;
How can I generate execution plan for a block like above?
I asked similar question earlier and decided to extract blocks from my stored procedure and generate execution plans for the individually. Though I know how to generate plans for simple queries, I dont know how to generate them for loop blocks like above.
Your PL/SQL block can be re-written in SQL:
INSERT INTO table2 (firstname, lastname)
SELECT fname, lastname
FROM table2
WHERE some_id IN (SELECT some_id FROM table1);
You can then "explain plan" the above INSERT.
If you have to do batch commits then using BULK COLLECT ... LIMIT and FORALL is more efficient than a cursor for loop, especially if you are processing millions of rows. Useful links:
You can't generate execution plans for PL/SQL
blocks, only for queries.
Execution plan shows how declarative commands ( SQL
) are executed under the hood, ie what procedures are used. It transforms the declarative constructs (set operations) into procedures (nested loops, hash joins, sorts etc).
PL/SQL
, being, as the name suggests, a procedural language, defines the execution plan itself — nested loops in your case.
If you want to see the execution plan for the inner query, you should copy it and issue EXPLAIN PLAN FOR …
Note that this can be more efficiently rewritten as:
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;
If you are interested in the performance of your procedural PL/SQL code you may want to investigate PL/SQL Profiling.
The Profiler allows you to collect information about the run-time performance of your PL/SQL. After the profiling run is complete you can report on the results and view information like # of times each line was executed, average execution time of each line. This can help you identify bottlenecks and should point you to the first things that may need tuning attention.
Your biggest potential payoff is by looking at the worst performing code and making it run better. Once that is improved, profile again to verify your improvements and to find the next statement that may need attention.
A good first introduction is here: Oracle's DBMS Profiler
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.