转-oracle pl/sql的批绑定和批量插入

来源:互联网 发布:php面向对象的实例 编辑:程序博客网 时间:2024/06/14 10:34

                            

 

当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

SQL
>
------------------------------------------------------------------

 

面我们使用上面那个例子中插入的100000条数据,来测试一下BULK COLLECT的威力。

代码:

SQL
> SET TIMING ON;
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  
  8    CURSOR c_data IS
  9      SELECT
*
10      FROM   test1;
11  BEGIN
12    
FOR cur_rec IN c_data LOOP
13      t_id
.extend;
14      t_description.extend;
15  
16      t_id
(t_id.last)                   := cur_rec.id;
17      t_description(t_description.last) := cur_rec.description;
18    END LOOP;
19  END;
20  /

PL/SQL procedure successfully completed

Executed in 2.974 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
;
  
6    t_description  description_type;
  
7  BEGIN
  8    SELECT id
, description
  9    BULK COLLECT INTO t_id
, t_description FROM test1;
10  END;
11  /

PL/SQL procedure successfully completed

Executed in 0.371 seconds

SQL
>



结论:当我们需要将大量的检索结果放入一个collection的时候,使用bulking将比直接使用cursor循环有效的多。

原创粉丝点击