日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

oracle 优化之批量处理bulk correct 和 forall

發布時間:2025/5/22 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 oracle 优化之批量处理bulk correct 和 forall 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

世風之狡詐多端,到底忠厚人顛撲不破; 末俗以繁華相尚,終覺冷淡處趣味彌長。

BULK? ?COLLECT運用

在游標中運用

declare?

cursor C_CUR is SELECT * FROM? T_TEST;

TYPE?T_TYPE IS TABLE OF??T_TEST%ROWTYPE;----需要定義一個數據記錄的類型

C_REC? T_TYPE;

begin?

open?C_CUR ;

loop

? FETCH??C_CUR BULK?COLLECT INTO?C_REC LIMIT 5000;?

?EXIT WHEN? C_REC.COUNT=0; ---這個地方不可以用? ?exit when?C_CUR%notfound 會導致少記錄? 如果用的話可以在循環結束的時候用,這是區別于普通游標的一個關鍵地方

?for I in?C_REC.first..C_REC.LAST?

?LOOP

?INSERT INTO MXQ(ID,NAME)? VALUES (C_REC(I).ID,C_REC(I).NAME);

UPDATE? MXQ? SET ID=C_REC(I).ID WHERE??NAME=C_REC(I).NAME;

END LOOP;

EXIT? WHEN?C_CUR%NOTFOUND;--粉色標明的地方 可以任意選擇一個退出循環

end loop;

close?C_CUR;

end;

forall 運用

forall也是一個集合提取 它不同于for循環的地方在于

1.它不是一個循環 不用接loop 和 end loop

?2.forall 后面只能跟一個dml語句.否則會報錯.

綜合運用BULK CORRECT 和?forall之后以上sql核心部分可以改寫成這樣?

loop

FETCH??C_CUR BULK?COLLECT INTO?C_REC LIMIT 5000;?

?EXIT WHEN? C_REC.COUNT=0;?

?forall I in?C_REC.first..C_REC.LAST?

INSERT INTO MXQ(ID,NAME)? VALUES (C_REC(I).ID,C_REC(I).NAME);----forall 后面只能跟一個dml語句

forall I in?C_REC.first..C_REC.LAST?

UPDATE? MXQ? SET ID=C_REC(I).ID WHERE??NAME=C_REC(I).NAME;

end loop;

關于fetch bulk collect into 游標記錄類型的聲明

聲明一個表中的記錄

DECLARE

CURSOR C_CUR IS SELECT * FROM TAB_TEST;

TYPE C_TYPE IS TABLE OF?TAB_TEST%ROWTYPE;

C_REC?C_TYPE;

聲明多個表中的記錄

DECLARE

CURSOR C_CUR IS SELECT A.ROWID,B.NAME FROM TAB_TEST_1 A,TAB_TEST_2 B WHERE A.ID=B.ID;

TYPE? C_TYPE_REC IS RECORD (ROWID? ? VARCHAR2(32),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NAME? ? ? TAB_TEST_2%TYPE );----因為是兩個表中的字段所以需要聲明一個記錄類型record包含這兩個表的字段

TYPE? C_TYPE IS TABLE OF?C_TYPE_REC;----把類型聲明成剛才那個記錄的類型,? 注意不需要%ROWTYPE? ?因為C_TYPE_REC已經是一個記錄類型了

C_REC?C_TYPE;

測試 效率? 數據270萬 環境11g

用BULK COLLECT? 和??forall?

寫法一

DECLARE?

CURSOR C_CUR IS SELECT A.ROWID FROM mxq A;
TYPE C_TYPE IS TABLE OF C_CUR%ROWTYPE;
C_REC C_TYPE;
BEGIN
OPEN C_CUR;
LOOP
FETCH C_CUR BULK COLLECT INTO C_REC LIMIT 10000;
EXIT WHEN C_REC.count=0;
FORALL I IN C_REC.FIRST..C_REC.LAST
UPDATE mxq A SET A.BEIZHU=(SELECT BEIZHU FROM mxq_1 B WHERE A.SNAME=B.SNAME ) WHERE A.ROWID=C_REC(I).ROWID;
commit;
END LOOP;
CLOSE C_CUR;
END; 222秒

寫法二

DECLARE
CURSOR C_CUR IS SELECT A.ROWID,B.BEIZHU FROM mxq A,mxq_1 B WHERE A.SNAME=B.SNAME;
TYPE C_TYPE IS TABLE OF C_CUR%ROWTYPE;
C_REC C_TYPE;
BEGIN
OPEN C_CUR;
LOOP
FETCH C_CUR BULK COLLECT INTO C_REC LIMIT 10000;
EXIT WHEN C_REC.count=0;
FORALL I IN C_REC.FIRST..C_REC.LAST
UPDATE mxq A SET A.BEIZHU=C_REC(I).BEIZHU WHERE A.ROWID=C_REC(I).ROWID;
commit;
END LOOP;
CLOSE C_CUR;
END; 267秒

這兩個寫法加載進游標的數據記錄不一樣經過測試發現 差距不大.

用兩種寫法分別使用批處理和不使用批處理

不用BULK COLLECT? 和??forall?

寫法一

?DECLARE?

CURSOR C_CUR IS SELECT A.ROWID FROM mxq A;
C_REC C_CUR%ROWTYPE;
BEGIN
OPEN C_CUR;
LOOP
FETCH C_CUR INTO C_REC ;
EXIT WHEN C_CUR%NOTFOUND;
UPDATE mxq A SET A.BEIZHU=(SELECT BEIZHU FROM mxq_1 B WHERE A.SNAME=B.SNAME ) WHERE A.ROWID=C_REC.ROWID;
commit;
END LOOP;
CLOSE C_CUR;
END;1000秒

?寫法二

DECLARE
CURSOR C_CUR IS SELECT A.ROWID,B.BEIZHU FROM mxq A,mxq_1 B WHERE A.SNAME=B.SNAME;
C_REC C_CUR%ROWTYPE;
BEGIN
OPEN C_CUR;
LOOP
FETCH C_CUR INTO C_REC ;
EXIT WHEN C_CUR%NOTFOUND;
UPDATE mxq A SET A.BEIZHU=C_REC.BEIZHU WHERE A.ROWID=C_REC.ROWID;
commit;
END LOOP;
CLOSE C_CUR;
END;804秒

不用批處理的dml語句 寫法二比寫法一快的明顯一些快了200秒.

總結

1.批處理比單條處理快了大概4倍.

2.sql寫法也一定程度上決定了dml的速度.

3可以用并發來提高dml速度,可以看我之前對并發做的測試.

最后送看文章的小伙伴一句話

乾坤未定,你我皆是黑馬.

轉載于:https://www.cnblogs.com/throughRiversandLake/p/10894482.html

總結

以上是生活随笔為你收集整理的oracle 优化之批量处理bulk correct 和 forall的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。