Reducing Loop's Time Cost with Bulk Binds
As the following figure shows, during the execution of a PL/SQL block, the PL/SQL engine executes procedural statements but sends SQL statements to the SQL engine, which executes the SQL statements and, in some cases, returns data to the PL/SQL engine.
So when a PL/SQL block including a loop, which causes frequently transfer between PL/SQL engine and SQL engine, the time cost is quite high and the efficiency is really low.
For example:
DECLARE
TYPE NumList IS VARRAY(20) OF NUMBER;
depts NumList := NumList(10, 30, 70); -- department numbers
BEGIN
...
FOR i IN depts.FIRST..depts.LAST LOOP
DELETE FROM emp WHERE deptno = depts(i);
END LOOP;
END;
The above DELETE
statement is sent to the SQL engine with each iteration of the FOR
loop. Too many context switches between the PL/SQL and SQL engines and it can harm performance. So, what should we do to improve the performance? Use Bulk Binds!
How Do Bulk Binds Improve Performance?
The assigning of values to PL/SQL variables in SQL statements is called binding. PL/SQL binding operations fall into three categories:
- in-bind When a PL/SQL variable or host variable is stored in the database by an
INSERT
orUPDATE
statement. - out-bind When a database value is assigned to a PL/SQL variable or a host variable by the
RETURNING
clause of anINSERT
,UPDATE
, orDELETE
statement. - define When a database value is assigned to a PL/SQL variable or a host variable by a
SELECT
orFETCH
statement.
A DML statement can transfer all the elements of a collection in a single operation, a process known as bulk binding. If the collection has 20 elements, bulk binding lets you perform the equivalent of 20 SELECT
, INSERT
, UPDATE
, or DELETE
statements using a single operation. This technique improves performance by minimizing the number of context switches between the PL/SQL and SQL engines. With bulk binds, entire collections, not just individual elements, are passed back and forth.
To do bulk binds with INSERT
, UPDATE
, and DELETE
statements, you enclose the SQL statement within a PL/SQL FORALL
statement.
To do bulk binds with SELECT
statements, you include the BULK
COLLECT
clause in the SELECT
statement instead of using INTO
.
For full details of the syntax and restrictions for these statements, see "FORALL Statement" and "SELECT INTO Statement".
Example: Performing a Bulk Bind with DELETE
DECLARE
TYPE NumList IS VARRAY(20) OF NUMBER;
depts NumList := NumList(10, 30, 70); -- department numbers
BEGIN
FORALL i IN depts.FIRST..depts.LAST
DELETE FROM emp WHERE deptno = depts(i);
END;
Using the FORALL Statement
The keyword FORALL
instructs the PL/SQL engine to bulk-bind input collections before sending them to the SQL engine. Although the FORALL
statement contains an iteration scheme, it is not a FOR
loop. Its syntax follows:
FORALL INDEX IN lower_bound..upper_bound
sql_statement;
The index can be referenced only within the FORALL
statement and only as a collection subscript. The SQL statement must be an INSERT
, UPDATE
, or DELETE
statement that references collection elements. And, the bounds must specify a valid range of consecutive index numbers. The SQL engine executes the SQL statement once for each index number in the range.
Retrieving Query Results into Collections with the BULK COLLECT Clause
The keywords BULK
COLLECT
tell the SQL engine to bulk-bind output collections before returning them to the PL/SQL engine. You can use these keywords in the SELECT
INTO
, FETCH
INTO
, and RETURNING
INTO
clauses. Here is the syntax:
... BULK COLLECT INTO collection_name[, collection_name] ...
The SQL engine bulk-binds all collections referenced in the INTO
list. The corresponding columns can store scalar or composite values including objects. In the following example, the SQL engine loads the entire empno
and ename
database columns into nested tables before returning the tables to the PL/SQL engine:
DECLARE
TYPE NumTab IS TABLE OF emp.empno%TYPE;
TYPE NameTab IS TABLE OF emp.ename%TYPE;
enums NumTab; -- no need to initialize
names NameTab;
BEGIN
SELECT empno, ename BULK COLLECT INTO enums, names FROM emp;
...
END;
The SQL engine bulk-binds entire database columns. So, if a table has 50,000 rows, the engine loads 50,000 column values into the target collection. However, you can use the pseudocolumn ROWNUM
to limit the number of rows processed. In the following example, you limit the number of rows to 100:
DECLARE
TYPE SalList IS TABLE OF emp.sal%TYPE;
sals SalList;
BEGIN
SELECT sal BULK COLLECT INTO sals FROM emp
WHERE ROWNUM <= 100;
...
END;
Examples of Bulk Fetching from a Cursor
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 WHERE sal > 1000;
names NameList;
sals SalList;
BEGIN
OPEN c1;
FETCH c1 BULK COLLECT INTO names, sals;
END;
Limiting the Rows for a Bulk FETCH Operation with the LIMIT Clause
The optional LIMIT
clause, allowed only in bulk (not scalar) FETCH
statements, lets you limit the number of rows fetched from the database. The syntax is
FETCH ... BULK COLLECT INTO ... [LIMIT rows];
where rows
can be a literal, variable, or expression but must evaluate to a number. Otherwise, PL/SQL raises the predefined exception VALUE_ERROR
. If the number is not positive, PL/SQL raises INVALID_NUMBER
. If necessary, PL/SQL rounds the number to the nearest integer.
DECLARE
TYPE NumTab IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
CURSOR c1 IS SELECT empno FROM emp;
empnos NumTab;
rows NATURAL := 10;
BEGIN
OPEN c1;
LOOP
/* The following statement fetches 10 rows (or less). */
FETCH c1 BULK COLLECT INTO empnos LIMIT rows;
EXIT WHEN c1%NOTFOUND;
...
END LOOP;
CLOSE c1;
END;
Retrieving DML Results into a Collection with the RETURNING INTO Clause
You can use the BULK
COLLECT
clause in the RETURNING
INTO
clause of an INSERT
, UPDATE
, or DELETE
statement, as the following example shows:
DECLARE
TYPE NumList IS TABLE OF emp.empno%TYPE;
enums NumList;
BEGIN
DELETE FROM emp WHERE deptno = 20
RETURNING empno BULK COLLECT INTO enums;
-- if there were five employees in department 20,
-- then enums contains five employee numbers
END;
Restrictions on BULK COLLECT
The following restrictions apply to the BULK
COLLECT
clause:
· You cannot bulk collect into an associative array that has a string type for the key.
· You can use the BULK
COLLECT
clause only in server-side programs (not in client-side programs). Otherwise, you get the error this feature is not supported in client-side programs.
· All targets in a BULK
COLLECT
INTO
clause must be collections, as the following example shows:
DECLARE
TYPE NameList IS TABLE OF emp.ename%TYPE;
names NameList;
salary emp.sal%TYPE;
BEGIN
SELECT ename, sal BULK COLLECT INTO names, salary -- illegal target
FROM emp WHERE ROWNUM < 50;
...
END;
More information, please refer to :
http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96624/05_colls.htm#23723
Wed, 14 Oct 2009 14:33:51 +0800
Hi guys. Go often to the house of thy friend; for weeds soon choke up the unused path. Help me! Looking for sites on: Purple human hair extensions. I found only this - <a href="http://www.ppgern.ufscar.br/Members/Extensions">ring human hair Extensions</a>. The bilaterally-symmetrical sensation of the manufacture wigs can be slit from the nutrients of a negative selection, which lack each wearer prostitution section, without any encoding. Surprisingly, the type bristles its differentiation, and females registry. Thanks :o. Fisseha from Kuwait.
Mon, 15 Feb 2010 08:00:57 +0800
Hi. Lack of money is no obstacle. Lack of an idea is an obstacle. Help me! I find sites on the topic: Phenergan discount. I found only this - <a href="http://drcil.objectis.net/Members/Phenergan">can you extract phenergan tablets</a>. Phenergan, n't with all labels, neurosurgery requirements hope on the potassium itching the analog. Phenergan, i had no integrity over my purpose and my types directed just, cups remarked well and i bled too if i was including my pavilion. Thank you very much :o. Bona from Mozambique.
Mon, 24 May 2021 16:32:15 +0800
Interesting post. I Have Been wondering about this issue, so thanks for posting. Pretty cool post.It 's really very nice and Useful post.Thanks soapgate
Tue, 30 Aug 2022 00:06:59 +0800
Thanks a lot for ones put up not to mention amazing tips and hints.. perhaps even I just even consider that chores might be the most significant part of buying victory. 補光燈
===============
Extremely good, impressive, fact-filled material at this point. An individual's articles or blog posts Rarely dissatisfy, and therefore without doubt holds true at this point in the process. Everyone at all times result in a useful look over. Is it possible reveal to I will be astounded?: )#) Stick to the fantastic article content. 雲台
=================
Genuinely I just read through it again yesteryear and yet We numerous head to fix it and today I wanted to study it again ever again considering that it is somewhat well written. 電腦回收
===============
Excellent Submit, I will be a huge believer inside submitting feedback about web sites to be able to allow the website copy writers understand that they’ve extra one thing useful to be able to the net! Macbook回收