pl/sql中的forall簡單測試
之前寫過一篇bulk collect的博文,只是對於bulk collect做了簡單的例項。http://blog.itpub.net/23718752/viewspace-1289696/
其實不光是bulk collect,forall對於pl/sql的效能的提升也是相當大的。
可以參見下面的兩個圖,可以看到其實在pl/sql中,可能很多時候我們所寫的pl/sql程式碼會在sql引擎和plsql引擎建進行上下文的切換,這個過程還是很耗費時間的。
![](https://i.iter01.com/images/8974a8cad106c433060f95a9d8b6000118e95775d1a98bb53749ca35969dac52.png)
而forall卻是相反,是提供一次上下文切換,會在forall的過程中進行資料的包裝處理。一次傳送給sql執行器去處理,大大減少了上下文切換時間。
![](https://i.iter01.com/images/7e2b89b0f3afecd48515e734923134b6772c73be10dcf9f898a5d1b19a988f7c.png)
對於此,可以想象,如果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來對此測試一下,可以看出在一些實現點中還是存在著很大的不同。
其實不光是bulk collect,forall對於pl/sql的效能的提升也是相當大的。
可以參見下面的兩個圖,可以看到其實在pl/sql中,可能很多時候我們所寫的pl/sql程式碼會在sql引擎和plsql引擎建進行上下文的切換,這個過程還是很耗費時間的。
![](https://i.iter01.com/images/8974a8cad106c433060f95a9d8b6000118e95775d1a98bb53749ca35969dac52.png)
而forall卻是相反,是提供一次上下文切換,會在forall的過程中進行資料的包裝處理。一次傳送給sql執行器去處理,大大減少了上下文切換時間。
![](https://i.iter01.com/images/7e2b89b0f3afecd48515e734923134b6772c73be10dcf9f898a5d1b19a988f7c.png)
對於此,可以想象,如果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來對此測試一下,可以看出在一些實現點中還是存在著很大的不同。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-1695028/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- bulk forall 的測試(轉)
- 使用profiler測試Oracle PL/SQL效能OracleSQL
- openGauss關於PL/SQL匿名塊呼叫測試SQL
- Oracle PL/SQL塊簡介OracleSQL
- [20240607]PL/SQL中sql語句的註解.txtSQL
- 簡單的 ping 測試
- Oracle PL/SQL程式碼中的註釋OracleSQL
- PL/SQL 宣告SQL
- Oracle PL/SQLOracleSQL
- 建立簡單的表測試
- try的簡單效能測試
- 單元測試:單元測試中的mockMock
- Hibernate對注入的簡單測試
- 讓 API 測試變的簡單API
- pl/sql to_dateSQL
- PL/SQL 運算子SQL
- PL/SQL 條件SQL
- PL/SQL 迴圈SQL
- PL/SQL 遊標SQL
- mysql簡單效能測試MySql
- Oracle logmnr簡單測試Oracle
- ORACLE PL/SQL 物件、表資料對比功能儲存過程簡單實現OracleSQL物件儲存過程
- Oracle 的PL/SQL語言使用OracleSQL
- 簡單的神經網路測試神經網路
- 使用PL/SQL找到兩個表中的相似值FKSQL
- java中的單元測試Java
- Jmeter效能測試簡單使用JMeter
- 【OracleEBS】 在PL/SQL中呼叫Oracle ERP請求OracleSQL
- 如何在PL/SQL中讀寫檔案(轉)SQL
- 【PG效能測試】pgbench效能測試工具簡單使用
- 一個簡單的介面測試框架 demo框架
- InnoSetup簡單教程一,安裝使用和簡單測試
- 記一次簡單的vue元件單元測試Vue元件
- 記一次想簡單化的單元測試
- PL/SQL中動態掉用儲存過程SQL儲存過程
- ultraedit高亮顯示pl/sqlSQL
- 簡單的11步在Laravel中實現測試驅動開發Laravel
- 簡單的 11 步在 Laravel 中實現測試驅動開發Laravel
- 簡單聊聊智慧硬體的韌體測試