You are on page 1of 6

PL/SQL Tuning

Using Bulk Binds and Collects

Contents
1. Introduction..................................................................................................................3
2. Pros and Cons of Bulk Binds.......................................................................................3
3. Retrieving data using Bulk Collect..............................................................................4
3.1 Without Bulk Collect.................................................................................................4
3.2 With Bulk Collect......................................................................................................4
4. Updating data using Bulk Bind....................................................................................5
4.1 Without Bulk Bind.....................................................................................................5
4.2 With Bulk Bind..........................................................................................................6

1
5. Conclusion.......................................................................................................................6

1. Introduction
The PL/SQL engine executes procedural statements and sends all SQL statements
present in the code to the SQL engine. The SQL engine will parse and execute the
query or DML statement and return the expected output back to the PL/SQL engine.
This switch between the two engines is called context switching.

2
We mostly concentrate on the SQL statement to tune performance issues. It is worth
noting that excessive context switching can affect performance. This would be
substantially significant when we are carrying out SQL statements in a loop. Since
context switches use CPU time, reducing the number of context switches will reduce
the amount of CPU time used.

Two PL/SQL features, Bulk Bind (Writing data in bulk) and Bulk collect (Reading data
in bulk) help in improving performance by utilizing resources effectively from within
PL/SQL code to reduce the context switching. These features were introduced in
Oracle 8i, are being improved on with every release.

Bulk Collects enable a PL/SQL program to fetch many rows from a cursor in one call
instead of fetching one row at a time. Bulk Binds also allow many similar DML
statements to be executed with one call instead of requiring a separate call for each.

2. Pros and Cons of Bulk Binds


PL/SQL code that uses bulk feature is slightly more complicated and more prone to
programmer bugs than code without bulk binds.

A PL/SQL program that reads a dozen rows from a cursor will probably see no
noticeable benefit from bulk binds. The same goes for a program that issues five or
six UPDATE statements. However, a program that reads 1,000 rows from a cursor or
performs that many similar UPDATE statements will most likely benefit from bulk
binds.

3. Retrieving data using Bulk Collect


The below code is written using with and with out Bulk feature to retrieve data from
a table and populate the collection objects.

3.1 Without Bulk Collect


DECLARE
TYPE namelist IS TABLE OF emp_info.ename%TYPE
INDEX BY BINARY_INTEGER;

3
TYPE sallist IS TABLE OF emp_info.sal%TYPE
INDEX BY BINARY_INTEGER;

CURSOR c1
IS
SELECT ename, sal
FROM emp_info;

names namelist;
sals sallist;
i NUMBER : = 0;
BEGIN
FOR rec_c1 IN c1
LOOP
names (i) := rec_c1.ename;
sals (i) := rec_c1.sal;
i := i + 1;
END LOOP;
END;

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 146939 1.57 1.33 0 146943 0 146939
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 146941 1.57 1.34 0 146943 0 146939

The above is a very simple program that does not use bulk binds. There were
146939 fetch calls against the cursor, requiring 146943 logical reads and
1.57 CPU seconds.

3.2 With Bulk Collect

DECLARE
TYPE NameList IS TABLE OF emp.ename%TYPE;
TYPE SalList IS TABLE OF emp.sal%TYPE;
CURSOR c1 IS SELECT ename, sal FROM emp_info;
names NameList;
sals SalList;
BEGIN
OPEN c1;
FETCH c1 BULK COLLECT INTO names, sals;
END;

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- --------
Parse 1 0.00 0.00 0 0 0 0

4
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.51 0.49 0 475 0 200000
------- ------ -------- ---------- ---------- ---------- ---------- --------
total 3 0.51 0.49 0 475 0 200000

The above is a very simple program which uses bulk binds. There were only 1
against the cursor instead of 146939, bringing logical reads down from 146943 to
475 and CPU time from 1.57 to 0.51 seconds.

4. Updating data using Bulk Bind

4.1 Without Bulk Bind


DECLARE
TYPE NumList IS VARRAY(20) OF NUMBER;
depts NumList := NumList(10, 20); -- department numbers
BEGIN
for i in depts.FIRST..depts.LAST
loop
UPDATE emp_info SET SAL=SAL*1.2 WHERE deptno = depts(i);
end loop;
END;

call count cpu elapsed disk query current rows


------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 2 57.23 108.76 0 14401 439532 200000
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 57.23 108.76 0 14401 439532 200000

In the above program, the UPDATE statement has taken 57 seconds CPU time to
execute. It got executed twice, as the number of departments were 2.

4.2 With Bulk Bind

DECLARE
TYPE NumList IS VARRAY(20) OF NUMBER;
depts NumList := NumList(10, 20); -- department numbers
BEGIN
FORALL i IN depts.FIRST..depts.LAST
UPDATE emp_info SET SAL=SAL*1.2 WHERE deptno = depts(i);
END;

call count cpu elapsed disk query current rows

5
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 0 0.00 0.00 0 0 0 0
Execute 1 0.00 0.01 0 0 0 0
Fetch 0 0.00 0.00 0 0 0 0
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 1 0.00 0.01 0 0 0 0

In the above program, the UPDATE statement was executed only once instead of
twice reducing CPU time from 57 seconds to 0 seconds.

5. Conclusion
In the above examples it appears that bulk binds were definitely worthwhile.
The CPU time was reduced by about 95%, elapsed time by about 90%, and logical
reads by about 80%.Since bulk binds reduce the number of SQL calls, SQL trace
adds much less overhead to code that uses bulk binds. While these TKPROF reports
suggest that in this example bulk binds saved about 90% off of the elapsed time.
Thus using bulk binds allow PL/SQL programs to interact more efficiently with the
SQL engine built into Oracle, enabling your PL/SQL programs to use less CPU time
and run faster.

You might also like