2006 年 10 月 17 日, 星期二
plsql表比游标更快
在遇到使用游标嵌套循环时,由于我们需要在里层循环里open和close游标,这样重复很多次,导致性能会很低下。此时可以使用plsql来改善性能。使用plsql,每个游标只需要open close一次。减少的时间不是一点两点。
下面的例子仅是简单的示范用法和性能对比,经过分别多次执行,得到时间如下:
使用plsql表的执行时间约在 0 . 04 秒。
而不使用plsql表的执行时间约在 8 . 33 秒。
create or replace procedure test_plsql_cursor
is
cursor cur_data_1 is
select tname,tabtype from tab;
cursor cur_data_2 is
select tname,tabtype from tab;
cursor cur_data_3 is
select tname,tabtype from tab;
---define record
type rectype_nametype is record (name varchar2(30),type varchar2(10));
---define plsql tab using record
type tab_nametype is table of rectype_nametype index by binary_integer;
---define plsql tab using cursor
type tab_type_1 is table of cur_data_1%rowtype index by binary_integer;
l_tab_1 cur_data_1%rowtype;
tab_1 tab_nametype;
tab_2 tab_type_1;
tab_3 tab_type_1;
l_tab_1_len int;
l_tab_2_len int;
l_tab_3_len int;
l_t int := 0;
begin
----------------------------
l_tab_1_len := 0;
open cur_data_1;
loop
fetch cur_data_1 into l_tab_1;
exit when cur_data_1%notfound;
tab_1(l_tab_1_len).name := l_tab_1.tname;
tab_1(l_tab_1_len).type := l_tab_1.tabtype;
l_tab_1_len := l_tab_1_len + 1;
end loop;
close cur_data_1;
l_tab_1_len := l_tab_1_len - 1;
----------------------------
l_tab_2_len := 0;
for I in cur_data_2
loop
tab_2(l_tab_2_len) := I;
l_tab_2_len := l_tab_2_len + 1;
end loop;
l_tab_2_len := l_tab_2_len - 1;
----------------------------
l_tab_3_len := 0;
for I in cur_data_3
loop
tab_3(l_tab_3_len) := I;
l_tab_3_len := l_tab_3_len + 1;
end loop;
l_tab_3_len := l_tab_3_len - 1;
-- loop test
for X in 0 .. l_tab_3_len
loop
for Y in 0 .. l_tab_2_len
loop
for Z in 0 .. l_tab_1_len
loop
l_t := l_t + 1;
end loop;
end loop;
end loop;
dbms_output.put_line ('l_t='||to_char(l_t));
end test_plsql_cursor;
/
create or replace procedure test_plsql_cursor_2
is
cursor cur_data_1 is
select tname,tabtype from tab;
cursor cur_data_2 is
select tname,tabtype from tab;
cursor cur_data_3 is
select tname,tabtype from tab;
---define plsql tab using cursor
type tab_type_1 is table of cur_data_1%rowtype index by binary_integer;
l_tab_1 cur_data_1%rowtype;
l_t int := 0;
begin
----------------------------
l_t := 0;
open cur_data_3;
loop
fetch cur_data_3 into l_tab_1;
exit when cur_data_3%notfound;
open cur_data_2;
loop
fetch cur_data_2 into l_tab_1;
exit when cur_data_2%notfound;
open cur_data_1;
loop
fetch cur_data_1 into l_tab_1;
exit when cur_data_1%notfound;
l_t := l_t + 1;
end loop;
close cur_data_1;
end loop;
close cur_data_2;
end loop;
close cur_data_3;
dbms_output.put_line ('l_t='||to_char(l_t));
end test_plsql_cursor_2;
/
其实时间是一样的
差别在于后者每次都在循环内部打开关闭游标,如果将3个游标均移至循环外打开关闭,则时间基本一样
create or replace procedure test_plsql_cursor_2
is
cursor cur_data_1 is
select tname,tabtype from tab;
cursor cur_data_2 is
select tname,tabtype from tab;
cursor cur_data_3 is
select tname,tabtype from tab;
---define plsql tab using cursor
type tab_type_1 is table of cur_data_1%rowtype index by binary_integer;
l_tab_1 cur_data_1%rowtype;
l_t int := 0;
begin
----------------------------
l_t := 0;
open cur_data_3;
open cur_data_2;
open cur_data_1;
loop
fetch cur_data_3 into l_tab_1;
exit when cur_data_3%notfound;
loop
fetch cur_data_2 into l_tab_1;
exit when cur_data_2%notfound;
loop
fetch cur_data_1 into l_tab_1;
exit when cur_data_1%notfound;
l_t := l_t + 1;
end loop;
end loop;
end loop;
close cur_data_1;
close cur_data_2;
close cur_data_3;
dbms_output.put_line ('l_t='||to_char(l_t));
end test_plsql_cursor_2;
这只是一个用空间换时间的方式
这只是一个用空间换时间的方式,在实际应用中还是需要根据具体情况而定的。
呵呵