当Oracle运行PL/SQL时会使用两套引擎,所有procedural code由PL/SQL engine 完成,所有SQL由SQL engine处理。所以如果Oracle从一个collection中循环执行相同的DML操作,那么为了避免两套engine切换所消耗的系统资源,可以使用bulk binds来把所有的DML操作binding到一次操作中完成。这将极大提高PL/SQL的执行效率。
 以下是简单的测试,用两种方式插入100000条数据,可以看到效率提高了7倍左右。
SQL> CREATE TABLE test1(
    2        id                     NUMBER(10),
    3        description    VARCHAR2(50));

Table created

SQL> ALTER TABLE test1 ADD (
    2         CONSTRAINT test1_pk PRIMARY KEY (id));

Table altered

SQL> SET TIMING ON;

SQL> DECLARE
    2        TYPE id_type                     IS TABLE OF test1.id%TYPE;
    3        TYPE description_type IS TABLE OF test1.description%TYPE;
    4
    5        t_id                     id_type                    := id_type();
    6        t_description    description_type := description_type();
    7     BEGIN
    8         FOR i IN 1 .. 100000 LOOP
    9            t_id.extend;
10            t_description.extend;
11
12            t_id(t_id.last)                                     := i;
13            t_description(t_description.last) := 'Description: ' || To_Char(i);
14         END LOOP;
15
16         FOR i IN t_id.first .. t_id.last LOOP
17             INSERT INTO test1 (id, description)
18             VALUES (t_id(i), t_description(i));
19         END LOOP;
20
21         COMMIT;
22     END;
23    /

PL/SQL procedure successfully completed

Executed in 141.233 seconds

SQL> truncate table test1;

Table truncated

Executed in 0.631 seconds

SQL>
SQL> DECLARE
    2        TYPE id_type                     IS TABLE OF test1.id%TYPE;
    3        TYPE description_type IS TABLE OF test1.description%TYPE;
    4
    5        t_id                     id_type                    := id_type();
    6        t_description    description_type := description_type();
    7     BEGIN
    8         FOR i IN 1 .. 100000 LOOP
    9            t_id.extend;
10            t_description.extend;
11
12            t_id(t_id.last)                                     := i;
13            t_description(t_description.last) := 'Description: ' || To_Char(i);
14         END LOOP;
15
16        FORALL i IN t_id.first .. t_id.last
17             INSERT INTO test1 (id, description)
18             VALUES (t_id(i), t_description(i));
19
20         COMMIT;
21     END;
22    /

PL/SQL procedure successfully completed

Executed in 27.52 seconds

SQL> select count(*) from test1;

     COUNT(*)
----------
        100000

Executed in 0.04 seconds