pl sql中的forall簡單測試

2021-09-22 19:14:33 字數 3009 閱讀 2363

之前寫過一篇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來對此測試一下,可以看出在一些實現點中還是存在著很大的不同。

FORALL與BULKCOLLECT的使用方法

1 使用forall比for效率高,因為前者只切換一次上下文,而後者將是在迴圈次數一樣多個上下文間切換。2 使用bluk collect一次取出乙個資料集合,比用游標條取資料效率高,尤其是在網路不大好的情況下。但bluk collect需要大量記憶體。使用例子 1 定義乙個table create ...

簡單的PLSQL應用

1.1連線本地資料庫 填入oracle主目錄 oci.dll檔案路徑 連線oracle遠端資料庫 填入客戶端oracle主目錄 oci.dll檔案路徑 客戶端和plsql位數需要匹配 編輯客戶端目錄下的network admin tnsnames.ora 檔案 修改遠端連線位址 埠等 若沒有該檔案需...

FOR迴圈與FORALL的效能比較

通常在sql語句中給pl sql變數賦值叫做繫結 binding 一次繫結乙個完整的集合稱為批量繫結 bulk binding 批量繫結 bulk binds 可以通過減少在pl sql和sql引擎之間的上下文切換 context switches 提高了效能.批量繫結 bulk binds 包括 ...