大量繫結(Bulk Binding)通過一次綁定一個完整的集合,然後在PL/SQL塊內部按照數組進行資料處理來加快SQL語句的效率。通過兩個DML語句:Bulk Collect和ForAll來實現。Bulk Collect—用來提高查詢(select)的效能ForAll—用來提高(Insert,Delete,Update)的效能。 國際慣例,描述一下測試環境:軟體環境 Windows 2000 + ORACLE9i 硬體環境 CPU 1.8G + RAM 512M 步驟一.建立一個測試表create table T3 (pid number(20),pname varchar2(50)); 步驟二.我們先測一下(10w筆) insert操作1.Loop迴圈declaretype IDTab is table of number(20) index by binary_integer;type NameTab is table of varchar2(50) index by binary_integer;pid IDTab;pname NameTab; begin for j in 1..100000 loop pid(j) := j; pname(j) := 'Name is ' || to_char(j); end loop; for i in 1..100000 loop insert into T3 values(pid(i),pname(i)); end loop;end;--耗時6.391s 2.使用FORALLdeclaretype IDTab is table of number(20) index by binary_integer;type NameTab is table of varchar2(50) index by binary_integer;pid IDTab;pname NameTab; begin for j in 1..100000 loop pid(j) := j; pname(j) := 'Name is ' || to_char(j); end loop; forall i in 1..100000 insert into T3 values(pid(i),pname(i));end;--耗時0.719s 效能差別太明顯了~~ 步驟三.我們再測一下(100w筆) insert操作1.Loop迴圈--耗時79.532s 2.使用FORALL--耗時274.056s 我們發現使用FORALL反而會比LOOP迴圈慢 3.使用FORALL 測50w--耗時 10.322s 4.使用FORALL 測80w--耗時 30.901s 5.使用FORALL 測80w--耗時 90.333s 現在不難理解了,由於批量執行資料的大小也會對結果產生重大影響,數組太大,佔用緩衝空間,增加了額外的開銷,本人的測試環境較弱,問題就反映了出來。 步驟四.解決方案 – 分批操作,每次10w筆,共10次declaretype IDTab is table of number(20) index by binary_integer;type NameTab is table of varchar2(50) index by binary_integer;pid IDTab;pname NameTab; n_count number;begin for j in 1..1000000 loop pid(j) := j; pname(j) := 'Name is ' || to_char(j); end loop; n_count := 100000; loop exit when n_count > 1000000; forall i in (n_count - 100000 + 1)..n_count insert into T3 values(pid(i),pname(i)); n_count := n_count + 100000; end loop;end;--耗時10.045s --分批操作,每次5w筆, 耗時7.609s--分批操作,每次1w筆, 耗時6.412s--分批操作,每次1k筆, 耗時6.5s可見不是我們需要經過多次反覆的測試才能得到一個合適的基數。 *Bulk Collect 的使用方法1.SELECT INTO中使用set serveroutput on;declaretype IDTab is table of T3.PID%type;type NameTab is table of T3.PNAME%type;pid IDTab;pname NameTab; beginselect pid,pname bulk collect into pid,pname from T3; for i in pid.first..1000 loop dbms_output.put_line(pid(i)||'-'||pname(i));end loop;end;/ 2.FETCH INTO中使用declaretype IDTab is table of T3.PID%type;type NameTab is table of T3.PNAME%type;pids IDTab;pnames NameTab;cursor c1 is select pid,pname from T3; beginopen c1;fetch c1 bulk collect into pids,pnames; for i in pids.first..1000 loop dbms_output.put_line(pids(i)||'-'||pnames(i));end loop;close c1;end;/
*參考資訊
http://search.itpub.net/search.php?s=3d0326caa48ee8542fced7da0ae6b785&action=showresults&searchid=392429&sortby=lastpost&sortorder=descendings=3d0326caa48ee8542fced7da0ae6b785&action=showresults&searchid=392429&sortby=lastpost&sortorder=descending