使用Bulk Collect提高Oracle查詢效率
Oracle8i中首次引入了Bulk Collect特性,該特性可以讓我們在PL/SQL中能使用批查詢,批查詢在某些情況下能顯著提高查詢效率。現在,我們對該特性進行一些簡單的測試和分析。
一、首先,我們創建一個表,并插入100000條記錄
在SQL/Plus中執行下列腳本:
drop table empl_tbl
/
create table empl_tbl(last_name varchar2(20),
first_name varchar2(10),
salary number(10))
/
begin
for i in 30000..1029999 loop
insert into empl_tbl(last_name,first_name,salary) values('carl'||(i-3000),'wu'||(1003000-i),i);
end loop;
end;
/
commit
/
select count(*) from empl_tbl;
/
二、使用三種方法計算表中某一字段含有多少個不重復值
2.1 使用常規的Distinct來實現
SQL> select count(distinct last_name) from empl_tbl;
Distinct Last Name
------------------
1000000
Executed in 1.531 seconds
我們可以看到,常規方法需要1.531 秒查出該表中有1000000個不重復的Last_name值。
2.2 使用游標來實現
我們執行下面語句來統計Last_name字段的不重復值個數:
CREATE OR REPLACE PROCEDURE tttt IS
all_rows number(10);
temp_last_name empl_tbl.last_name%type;
begin
all_rows:=0;
temp_last_name:=' ';
for cur in (select last_name from empl_tbl order by last_name) loop
if cur.last_name!=temp_last_name then
all_rows:=all_rows+1;
end if;
temp_last_name:=cur.last_name;
end loop;
dbms_output.put_line('all_rows are '||all_rows);
end;
請注意上面代碼中的黑體部分使用了一個For Loop游標,為了提高程序可讀性,我們沒有顯示定義游標變量。
執行結果:
all_rows are 1000000
PL/SQL procedure successfully completed
Executed in 10.39 seconds
游標需要10.396秒才能查出該表中有1000000個不重復的Last_name值,所耗時間是Distinct查詢的10倍多。
2.3 使用Bulk Collect批查詢來實現
示例代碼如下:
declare
all_rows number(10);
--首先,定義一個Index-by表數據類型
type last_name_tab is table of empl_tbl.last_name%type index by binary_integer;
last_name_arr last_name_tab;
--定義一個Index-by表集合變量
temp_last_name empl_tbl.last_name%type;
begin
all_rows:=0;
temp_last_name:=' ';
--使用Bulk Collect批查詢來充填集合變量
select last_name bulk collect into last_name_arr from empl_tbl;
for i in 1..last_name_arr.count loop
if temp_last_name!=last_name_arr(i) then
all_rows:=all_rows+1;
end if;
temp_last_name:=last_name_arr(i);
end loop;
dbms_output.put_line('all_rows are '||all_rows);
end;
請注意上面代碼中,我們首先定義了一個Index-by表數據類型last_name_tab,然后定義了一個該集合數據類型的變量last_name_arr,最后我們使用Bulk Collect批查詢來充填last_name_arr,請注意它
的使用語法。
執行結果:
all_rows are 1000000
PL/SQL procedure successfully completed
Executed in 2.343 seconds
從上面執行結果,我們可以看到,Bulk Collect批查詢只需要2.343 秒就能查出該表中有1000000個不重復的Last_name值,所耗時間只有游標查詢的1/2.5。
三. 測試結果分析
三. 測試結果分析
為什么會出現上面的結果呢?我們可以使用Oracle的SQL_Trace來分析一下結果。在SQL命令行中,使用alter session set sql_trace=true語句打開Oracle的Trace,然后在命令行中執行上面三種查詢并使用TKPROF工具生成Trace報告。
3.1 常規Distinct查詢結果分析
3.2 游標查詢效率分析
3.3 Bulk Collect的查詢效率分析
四. 結論
通過上面的測試和分析,我們可以看到Bulk Collect批查詢在某種程度上可以提高查詢效率,它首先將所需數據讀入內存,然后再統計分析,這樣就可以提高查詢效率。但是,如果Oracle數據庫的內存較小,Shared Pool Size不足以保存Bulk Collect批查詢結果,那么該方法需要將Bulk Collect的集合結果保存在磁盤上,在這種情況下,Bulk Collect方法的效率反而不如其他兩種方法,有興趣的讀者可以進一步測試。
另外,除了Bulk Collect批查詢外,我們還可以使用FORALL語句來實現批插入、刪除和更新,這在大批量數據操作時可以顯著提高執行效率。
名稱: ?4C.ESL | .↗Evon
口號: 遇到新問題?先要尋找一個方案乄而不是創造一個方案こ
mail: 聯系我