J2EE社區

          茍有恒,何必三更起五更眠;
          最無益,只怕一日曝十日寒.
          posts - 241, comments - 318, trackbacks - 0, articles - 16

          使用Bulk Collect提高Oracle查詢效率

          Posted on 2011-12-31 15:03 xcp 閱讀(1299) 評論(0)  編輯  收藏 所屬分類: Database
          使用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: 聯系我


          主站蜘蛛池模板: 邮箱| 额尔古纳市| 斗六市| 巴南区| 鄂尔多斯市| 玉门市| 名山县| 天峻县| 南昌市| 白玉县| 高阳县| 张北县| 常州市| 顺昌县| 凤台县| 辽源市| 南投市| 城口县| 定安县| 桂林市| 桐乡市| 伊金霍洛旗| 鄂尔多斯市| 乌拉特中旗| 大城县| 从化市| 闸北区| 周至县| 乳山市| 鄂伦春自治旗| 固原市| 新兴县| 临夏市| 乌兰察布市| 隆昌县| 福泉市| 甘孜| 中西区| 海淀区| 秀山| 佛学|