連續插值,用forall實現。

lsl031發表於2007-09-02

最開始考慮用記錄表實現,如下的過程。但除錯時出現錯誤。

提示不能引用記錄來實現。PL/SQL: ORA-22806: 不是物件或 REF

set serverout on
declare
i number;
type large_type_no is table number;
type large_type_desc is table varchar2(12);
type large_type_desc1 is table varchar2(12);
large_table large_type;
large_desc large_type_desc;
large_desc1 large_type_desc1;
start_time number(10);
stop_time number(10);
begin
start_time:=dbms_utility.get_time;
for i in 1..1000000 loop
large_table(i):=i+3000000;
large_desc(i):='very fat';
large_desc1(i):='tool';
end loop;
forall i in 1..large_table.count
insert into large1 values(large_table(i),large_desc(i),large_desc1(i));
stop_time:=dbms_utility.get_time;
dbms_output.put_line('總計時間:'|| to_char((start_time-stop_time)/100));
end;
/


SQL> @c: est.sql;
insert into large1 values(large_table(i).no,large_table(i).no_desc,large_table(i
).se_desc);
*
第 15 行出現錯誤:
ORA-06550: 第 15 行, 第 27 列:
PLS-00436: 實施限制: 不能引用記錄的 BULK In-BIND 表的欄位
ORA-06550: 第 15 行, 第 27 列:
PLS-00382: 表示式型別錯誤
ORA-06550: 第 15 行, 第 45 列:
PLS-00436: 實施限制: 不能引用記錄的 BULK In-BIND 表的欄位
ORA-06550: 第 15 行, 第 45 列:
PLS-00382: 表示式型別錯誤
ORA-06550: 第 15 行, 第 68 列:
PLS-00436: 實施限制: 不能引用記錄的 BULK In-BIND 表的欄位
ORA-06550: 第 15 行, 第 68 列:
PLS-00382: 表示式型別錯誤
ORA-06550: 第 15 行, 第 27 列:
PL/SQL: ORA-22806: 不是物件或 REF
ORA-06550: 第 15 行, 第 1 列:
PL/SQL: SQL Statement ignored

然後每個欄位用了一個索引表來實現。

set serverout on
declare
i number;
type large_type_no is table of number index by binary_integer;
type large_type_desc is table of varchar2(12) index by binary_integer;
type large_type_desc1 is table of varchar2(12) index by binary_integer;
large_table large_type_no ;
large_desc large_type_desc;
large_desc1 large_type_desc1;

start_time number(10);
stop_time number(10);
begin

start_time:=dbms_utility.get_time;

for i in 1..1000000 loop
large_table(i):=i+3000000;
large_desc(i):='very fat';
large_desc1(i):='tool';
end loop;
forall i in 1..large_table.count
insert into large1 values(large_table(i),large_desc(i),large_desc1(i));

dbms_output.put_line(large_table.count);
stop_time:=dbms_utility.get_time;
dbms_output.put_line('總計時間:'|| to_char((start_time-stop_time)/100));
end;
/
SQL> @c: est2.sql;
1000000
總計時間:-33.11

PL/SQL 過程已成功完成。

用時33秒,插入100萬條記錄。

而不用批次插入時,以下指令碼:

set serverout on
declare
i number;
start_time number(10);
stop_time number(10);
begin
start_time:=dbms_utility.get_time;
for i in 4000001..5000000 loop
insert into large1 values(i,'safsf','fdgfdgfdg');
end loop;
stop_time:=dbms_utility.get_time;

dbms_output.put_line('總計時間:'|| to_char((start_time-stop_time)/100));
end;
/

SQL> @c: est.sql;
總計時間:-152.03

PL/SQL 過程已成功完成。

100萬用時152秒,是批次的5倍。當然排除掉因為資料增加而造成的寫入成本。但效能提升還是很顯著的。

註釋:forall和bulk collect是對利用多維物件來一次性對資料進行sql操作,減少了pl/sql 和sql間的上下文切換而浪費的時間和資源。對記錄的單條處理,放入了對物件的迴圈處理中,此時全部由pl/sql完成,不需要sql的接介入。

[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/288166/viewspace-967574/,如需轉載,請註明出處,否則將追究法律責任。

相關文章