1. 程式人生 > 其它 >oracle中bulk collect into用法

oracle中bulk collect into用法

通過bulk collect減少loop處理的開銷 
 
採用bulk collect可以將查詢結果一次性地載入到collections中。 
而不是通過cursor一條一條地處理。 
可以在select into,fetch into,returning into語句使用bulk collect。 
注意在使用bulk collect時,所有的into變數都必須是collections. 
 
 
舉幾個簡單的例子: 
--在select into語句中使用bulk collect 
DECLARE 
TYPE SalList IS TABLE OF emp.sal%TYPE; 
sals SalList; 
BEGIN -- Limit the number of rows to 100. SELECT sal BULK COLLECT INTO sals FROM emp WHERE ROWNUM <= 100; -- Retrieve 10% (approximately) of the rows in the table. SELECT sal BULK COLLECT INTO sals FROM emp SAMPLE 10; END; / --在fetch into中使用bulk collect DECLARE TYPE DeptRecTab IS TABLE OF dept%
ROWTYPE; dept_recs DeptRecTab; CURSOR c1 IS SELECT deptno, dname, loc FROM dept WHERE deptno > 10; BEGIN OPEN c1; FETCH c1 BULK COLLECT INTO dept_recs; END; / --在returning into中使用bulk collect CREATE TABLE emp2 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 FROM emp2 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; / DROP TABLE emp2;

如果有個大資料量的DML操作事務,在OLAP報表等低併發庫裡. 並且強制歸檔模式中.

採用BULK 和FORALL 會比較快!

open cur_COLUMN_USER;
  loop
   fetch cur_COLUMN_USER bulk collect
   into 
          l_ARY_statedate,                    
          l_ARY_form,
          l_ARY_columnid,           
          l_ARY_usernumber,                   
          l_ARY_new_user,               
          l_ARY_exit_use    
   limit g_batch_size_n;
   
   forall i in 1..l_ARY_statedate.count
    insert into content_lst_day
    (......)
    values(l_ary_statedate(i),....);
 
 commit;
end loop;
相對使用普通遊標迴圈提取資料出來處理的話 會快很多.

原因 1 bulk collect into 到陣列 可以一次型把資料提取出來,減少了迴圈當中PL/SQL和SQL引撐的切換時間

原因 2 forall in ..... 也是一次型提交資料到某個地方 也同樣減少了迴圈當中PL/SQL和SQL引撐的切換時間

注意 1 資料太大 要設定合理的LIMIT 否則提取到陣列的資料會爆了PGA的回話記憶體

原因 3 bulk 內部操作 對insert delete 做了優化 採用批量方法.極大減少了redo 和Undo 使用量.

原因 4 為證明 當一個大資料量的insert 會超級慢,如果分批插入的總時間 比一次插入省很多時間.

An ORA-22813 when using BULK COLLECT is typically expected behavior indicating that you have exceeded the amount of free memory in the PGA. As collections are processed by PL/SQL they use the PGA to store their memory structures. Depending on the LIMIT size of the BULK COLLECT and additional processing of the collected data you may exceed the free memory of the PGA. While intuitively you may think that increasing the PGA memory and increasing the LIMIT size will increase performance, the following example shows you that this is not true in this case. So, by reviewing this example you should be able to strike a balance between a reasonable LIMIT size and the size of the PGA while maintaining a high level of performance using BULK COLLECT.

好的程式碼像粥一樣,都是用時間熬出來的