濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > 淺談PL/SQL批處理語(yǔ)句:BULK COLLECT與FORALL對(duì)優(yōu)化做出的貢獻(xiàn)

淺談PL/SQL批處理語(yǔ)句:BULK COLLECT與FORALL對(duì)優(yōu)化做出的貢獻(xiàn)

熱門(mén)標(biāo)簽:百度地圖標(biāo)注素材 征服者火車站地圖標(biāo)注 外呼線路外顯本地號(hào)碼 word地圖標(biāo)注方向 美圖秀秀地圖標(biāo)注 開(kāi)封智能外呼系統(tǒng)廠家 人工智能地圖標(biāo)注自己能做嗎 阿爾巴尼亞地圖標(biāo)注app 征服眼公司地圖標(biāo)注
我們知道PL/SQL程序中運(yùn)行SQL語(yǔ)句是存在開(kāi)銷的,因?yàn)镾QL語(yǔ)句是要提交給SQL引擎處理
這種在PL/SQL引擎和SQL引擎之間的控制轉(zhuǎn)移叫做上下文卻換,每次卻換時(shí),都有額外的開(kāi)銷

請(qǐng)看下圖:

但是,F(xiàn)ORALL和BULK COLLECT可以讓PL/SQL引擎把多個(gè)上下文卻換壓縮成一個(gè),這使得在PL/SQL中的要處理多行記錄的SQL語(yǔ)句執(zhí)行的花費(fèi)時(shí)間驟降
請(qǐng)?jiān)倏聪聢D:

下面詳解這爺倆

㈠ 通過(guò)BULK COLLECT 加速查詢

⑴ BULK COLLECT 的用法


采用BULK COLLECT可以將查詢結(jié)果一次性地加載到collections中,而不是通過(guò)cursor一條一條地處理
可以在select into ,fetch into , returning into語(yǔ)句使用BULK COLLECT
注意在使用BULK COLLECT時(shí),所有的INTO變量都必須是collections

舉幾個(gè)簡(jiǎn)單例子:

① 在select into語(yǔ)句中使用bulk collect

復(fù)制代碼 代碼如下:

DECLARE
TYPE sallist IS TABLE OF employees.salary%TYPE;
sals sallist;
BEGIN
SELECT salary BULK COLLECT INTO sals FROM employees where rownum=50;
--接下來(lái)使用集合中的數(shù)據(jù)
END;
/

② 在fetch into中使用bulk collect

復(fù)制代碼 代碼如下:

DECLARE
TYPE deptrectab IS TABLE OF departments%ROWTYPE;
dept_recs deptrectab;
CURSOR cur IS SELECT department_id,department_name FROM departments where department_id>10;
BEGIN
OPEN cur;
FETCH cur BULK COLLECT INTO dept_recs;
--接下來(lái)使用集合中的數(shù)據(jù)
END;
/

③ 在returning into中使用bulk collect

復(fù)制代碼 代碼如下:

CREATE TABLE emp AS SELECT * FROM employees;

DECLARE
TYPE numlist IS TABLE OF employees.employee_id%TYPE;
enums numlist;
TYPE namelist IS TABLE OF employees.last_name%TYPE;
names namelist;
BEGIN
DELETE emp WHERE department_id=30
RETURNING employee_id,last_name BULK COLLECT INTO enums,names;
DBMS_OUTPUT.PUT_LINE('deleted'||SQL%ROWCOUNT||'rows:');
FOR i IN enums.FIRST .. enums.LAST
LOOP
DBMS_OUTPUT.PUT_LINE('employee#'||enums(i)||':'||names(i));
END LOOP;
END;
/

deleted6rows:
employee#114:Raphaely
employee#115:Khoo
employee#116:Baida
employee#117:Tobias
employee#118:Himuro
employee#119:Colmenares

EATE TABLE emp AS SELECT * FROM employees;DECLARE TYPE numlist IS TABLE OF employees.employee_id%TYPE; enums numlist; TYPE namelist IS TABLE OF employees.last_name%TYPE; names namelist;BEGIN DELETE emp WHERE department_id=30 RETURNING employee_id,last_name BULK COLLECT INTO enums,names; DBMS_OUTPUT.PUT_LINE('deleted'||SQL%ROWCOUNT||'rows:'); FOR i IN enums.FIRST .. enums.LAST LOOP DBMS_OUTPUT.PUT_LINE('employee#'||enums(i)||':'||names(i)); END LOOP;END;/deleted6rows:employee#114:Raphaelyemployee#115:Khooemployee#116:Baidaemployee#117:Tobiasemployee#118:Himuroemployee#119:Colmenares


⑵ BULK COLLECT 對(duì)大數(shù)據(jù)DELETE UPDATE的優(yōu)化

這里舉DELETE就可以了,UPDATE同理

舉個(gè)案例:
需要在一個(gè)1億行的大表中,刪除1千萬(wàn)行數(shù)據(jù)
需求是在對(duì)數(shù)據(jù)庫(kù)其他應(yīng)用影響最小的情況下,以最快的速度完成

如果業(yè)務(wù)無(wú)法停止的話,可以參考下列思路:
根據(jù)ROWID分片、再利用Rowid排序、批量處理、回表刪除
在業(yè)務(wù)無(wú)法停止的時(shí)候,選擇這種方式,的確是最好的
一般可以控制在每一萬(wàn)行以內(nèi)提交一次,不會(huì)對(duì)回滾段造成太大壓力
我在做大DML時(shí),通常選擇一兩千行一提交
選擇業(yè)務(wù)低峰時(shí)做,對(duì)應(yīng)用也不至于有太大影響
代碼如下:

復(fù)制代碼 代碼如下:

DECLARE
--按rowid排序的cursor
--刪除條件是oo=xx,這個(gè)需根據(jù)實(shí)際情況來(lái)定
CURSOR mycursor IS SELECT rowid FROM t WHERE OO=XX ORDER BY rowid;
TYPE rowid_table_type IS TABLE OF rowid index by pls_integer;
v_rowid rowid_table_type;
BEGIN
OPEN mycursor;
LOOP
FETCH mycursor BULK COLLECT INTO v_rowid LIMIT 5000;--5000行提交一次
EXIT WHEN v_rowid.count=0;
FORALL i IN v_rowid.FIRST..v_rowid.LAST
DELETE t WHERE rowid=v_rowid(i);
COMMIT;
END LOOP;
CLOSE mycursor;
END;
/

⑶ 限制BULK COLLECT 提取的記錄數(shù)

語(yǔ)法:
FETCH cursor BULK COLLECT INTO ...[LIMIT rows];
其中,rows可以是常量,變量或者求值的結(jié)果是整數(shù)的表達(dá)式

假設(shè)你需要查詢并處理1W行數(shù)據(jù),你可以用BULK COLLECT一次取出所有行,然后填充到一個(gè)非常大的集合中
可是,這種方法會(huì)消耗該會(huì)話的大量PGA,APP可能會(huì)因?yàn)镻GA換頁(yè)而導(dǎo)致性能下降

這時(shí),LIMIT子句就非常有用,它可以幫助我們控制程序用多大內(nèi)存來(lái)處理數(shù)據(jù)

例子:

復(fù)制代碼 代碼如下:

DECLARE
CURSOR allrows_cur IS SELECT * FROM employees;
TYPE employee_aat IS TABLE OF allrows_cur%ROWTYPE INDEX BY BINARY_INTEGER;
v_emp employee_aat;
BEGIN
OPEN allrows_cur;
LOOP
FETCH allrows_cur BULK FETCH INTO v_emp LIMIT 100;

/*通過(guò)掃描集合對(duì)數(shù)據(jù)進(jìn)行處理*/
FOR i IN 1 .. v_emp.count
LOOP
upgrade_employee_status(v_emp(i).employee_id);
END LOOP;

EXIT WHEN allrows_cur%NOTFOUND;
END LOOP;

CLOSE allrows_cur;
END;
/

⑷ 批量提取多列

需求:
提取transportation表中的油耗小于 20公里/RMB的交通具體的全部信息
代碼如下:

復(fù)制代碼 代碼如下:

DECLARE
--聲明集合類型
TYPE vehtab IS TABLE OF transportation%ROWTYPE;
--初始化一個(gè)這個(gè)類型的集合
gas_quzzlers vehtab;
BEGIN
SELECT * BULK COLLECT INTO gas_quzzlers FROM transportation WHERE mileage 20;
...

⑸ 對(duì)批量操作使用RETURNING子句

有了returning子句后,我們可以輕松地確定剛剛完成的DML操作的結(jié)果,無(wú)須再做額外的查詢工作
例子請(qǐng)見(jiàn)BULK COLLECT 的用法的第三小點(diǎn)


㈡ 通過(guò)FORALL 加速DML

FORALL告訴PL/SQL引擎要先把一個(gè)或多個(gè)集合的所有成員都綁定到SQL語(yǔ)句中,然后再把語(yǔ)句發(fā)送給SQL引擎

⑴ 語(yǔ)法

未完待續(xù)。。。

您可能感興趣的文章:
  • 開(kāi)啟SQLSERVER數(shù)據(jù)庫(kù)緩存依賴優(yōu)化網(wǎng)站性能
  • SQLServer 優(yōu)化SQL語(yǔ)句 in 和not in的替代方案
  • SQL語(yǔ)句優(yōu)化方法30例(推薦)
  • SQL Server數(shù)據(jù)庫(kù)的高性能優(yōu)化經(jīng)驗(yàn)總結(jié)
  • MySQL 大數(shù)據(jù)量快速插入方法和語(yǔ)句優(yōu)化分享
  • MySQL性能優(yōu)化的一些技巧幫助你的數(shù)據(jù)庫(kù)
  • MySQL查詢優(yōu)化:連接查詢排序limit(join、order by、limit語(yǔ)句)介紹
  • 淺談MySQL中優(yōu)化sql語(yǔ)句查詢常用的30種方法
  • 如何優(yōu)化SQL語(yǔ)句的心得淺談
  • SQL語(yǔ)句優(yōu)化提高數(shù)據(jù)庫(kù)性能

標(biāo)簽:泰安 海北 葫蘆島 孝感 酒泉 淮南 六安 宜春

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《淺談PL/SQL批處理語(yǔ)句:BULK COLLECT與FORALL對(duì)優(yōu)化做出的貢獻(xiàn)》,本文關(guān)鍵詞  淺談,SQL,批處理,語(yǔ)句,BULK,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《淺談PL/SQL批處理語(yǔ)句:BULK COLLECT與FORALL對(duì)優(yōu)化做出的貢獻(xiàn)》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于淺談PL/SQL批處理語(yǔ)句:BULK COLLECT與FORALL對(duì)優(yōu)化做出的貢獻(xiàn)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    海晏县| 射阳县| 得荣县| 丹寨县| 安泽县| 广宗县| 札达县| 南部县| 淅川县| 孙吴县| 高平市| 瓦房店市| 普陀区| 德安县| 东乌| 洞口县| 循化| 仁寿县| 托里县| 静海县| 盐山县| 盐边县| 彭山县| 宾川县| 两当县| 喀喇沁旗| 梅河口市| 祁门县| 枣庄市| 呼伦贝尔市| 巢湖市| 卓资县| 临沧市| 兖州市| 镇沅| 雷州市| 尚志市| 高陵县| 昌江| 崇阳县| 错那县|