天天看點

多行資料的批處理之bulk collect

在寫pl/sql的時候,很多時候都會用比較經典的模式,定義一個遊标cursor,然後循環從遊标中取值進行處理。

類似下面的格式

declare

cursor xxxx is xxxxx;

begin

loop cur in xxxxx loop

xxxxx

end loop;

end;

/

如果cursor中包含的資料太多的時候,可能會有性能問題,性能的考慮主要在于pl/sql引擎和sql引擎的切換,和程式設計中的上下文環境是類似的。

這個時候可以考慮采用bulk collect 的方式直接一次性讀取資料島緩存然後從緩存中進一步處理。

這種方式可以打個比方比較形象,比如 你帶着一個新人去完成一個任務,可能一天他要問你100個問題,你是希望他每隔幾分鐘想到了就問你呢,還是讓他自己把問題積累起來,專門設定一個時間來集中回答呢。可能你在忙另外一個事情,他問你一個問題,這個時候就會有上下文環境的切換,等你回答了之後,繼續工作的時候,又一個問題來了,這時候又得進行一次切換。。。。

比方說我們設定一個表test,希望把test裡面的資料選擇性的插入到test_all中去

實作的原始Pl/sql如下:

cursor test_cursors is select object_id,object_name from test;

for test_cursor in test_cursors loop

dbms_output.put_line('object_id: '||test_cursor.object_id);

insert into test_all values(test_cursor.object_id,test_cursor.object_name);

commit;

如果采用bulk collect 方式,就會是如下的方式:

 declare

 type id_t is table of test.object_id%type;

 type name_t is table of test.object_name%type;

 object_id id_t;

 object_name name_t;

 cursor test_cursors is select object_id,object_name from test;

 begin

 open test_cursors;

 fetch test_cursors bulk collect into object_id,object_name;

 close test_cursors;

 for i in object_id.FIRST .. object_id.LAST loop

  dbms_output.put_line('object_id: '||object_id(i));

 insert into test_all values(object_id(i),object_name(i));

 end loop;

 commit;

 end;

 /

或者采用隐式遊标的方式:

  select object_id,object_name bulk collect into object_id,object_name from test where rownum