PL/SQL中的forall簡單測試

來源:互聯網
上載者:User

PL/SQL中的forall簡單測試

之前寫過一篇bulk collect的文章,只是對於bulk collect做了簡單的執行個體。
其實不光是bulk collect,forall對於pl/sql的效能的提升也是相當大的。
 可以參見下面的兩個圖,可以看到其實在pl/sql中,可能很多時候我們所寫的pl/sql代碼會在sql引擎和plsql引擎建進行內容相關的切換,這個過程還是很耗費時間的。

 而forall卻是相反,是提供一次環境切換,會在forall的過程中進行資料的封裝處理。一次發送給sql執行器去處理,大大減少了環境切換時間。

 對於此,可以想象,如果cursor中的結果集很龐大,就很可能進行大量的環境切換,導致執行速度驟降。
 我們來做一個簡單的執行個體來說明一下。

 我們建立一個表test_data,裡面大概有7萬多的資料量。
n1@TEST11G> create table test_data as select *from all_objects;
 Table created.

 n1@TEST11G> select count(*)from test_data;
  COUNT(*)
 ----------
      71659
 1 row selected

n1@TEST11G> create unique index inx_test_data_pk on test_data(object_id);
Index created.
Elapsed: 00:00:00.48

然後就開始執行預存程序
[ora11g@oel1 plsql]$ cat a.sql
create or replace procedure test_proc as 
  cursor test_cur is select *from test_data;
  i number;
begin
  i:=1;
  for cur in test_cur
  loop
  update test_data set object_name=cur.object_name
where object_id=cur.object_id;
  dbms_output.put_line('this is a test');
  i:=i+1;
  end loop;
end;
/

 exec test_proc;

執行的過程中會看到進程佔用了大量的cpu資源。可見進行了大量的環境切換。其實一個主要的資訊點就是可以看到輸出了大量的日誌內容,最後還因為緩衝的原因退出了。

......
this is a test
 this is a test
 this is a test
 this is a test
 this is a test
 this is a test
 this is a test
 this is a test
 this is a test
 this is a test
 this is a test
 this is a test
 this is a test
 this is a test
 this is a test
 BEGIN test_proc; END;

 *
 ERROR at line 1:
 ORA-20000: ORU-10027: buffer overflow, limit of 1000000 bytes
 ORA-06512: at "SYS.DBMS_OUTPUT", line 32
 ORA-06512: at "SYS.DBMS_OUTPUT", line 97
 ORA-06512: at "SYS.DBMS_OUTPUT", line 112
 ORA-06512: at "N1.TEST_PROC", line 10
 ORA-06512: at line 1

Elapsed: 00:00:13.73

同樣的要求,如果使用forall的形式,使用的代碼如下。
[ora11g@oel1 plsql]$ cat b.sql
create or replace procedure test_proc as 
  cursor test_cur is select *from test_data;
  type rec_type is table of test_cur%rowtype index by binary_integer;
  recs rec_type;
begin
  open test_cur;
  fetch test_cur bulk collect into recs;
  close test_cur;
  forall i in 1..recs.COUNT
  update test_data set object_name=recs(i).object_name
where object_id=recs(i).object_id;
  dbms_output.put_line('this is a test');
end;
/

這種效果就好得多,可以看到日誌中只輸出了一次日誌資訊,意味著只進行了一次環境切換,這種方法明顯要好很多。
n1@TEST11G> exec test_proc;
this is a test
PL/SQL procedure successfully completed.
Elapsed: 00:00:01.67
對於大批量的資料處理還是很值得推薦的。後續會使用dbms_profiler來對此測試一下,可以看出在一些實現點中還是存在著很大的不同。

Oracle資料庫之PL/SQL程式基礎設計 

PL/SQL Developer實用技巧分享

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.