`

forall与bulk collect 节约时间的例子

阅读更多

(1)看看下面一段pl/sql:

begin
update T2 set  ... where
T2.F1 in ( SELECT T1.F1 FROM T1 WHERE  T1.F2='2009');

update T3 set  ... where
T3.F1 in ( SELECT T1.F1 FROM T1 WHERE  T1.F2='2009');

update T4 set  ... where
T4.F1 in ( SELECT T1.F1 FROM T1 WHERE  T1.F2='2009');
end;

感觉效率不太好,而且写法也有点冗余,把 SELECT T1.F1 FROM T1 WHERE  T1.F2='2009’写了三遍,而且每次更新都要执行这个查询,万一这个查询是个很耗时的操作,那么也太影响效率了;

 

这个也可以用临时表

(2)可以用forall

TYPE T_F1 IS TABLE OF varchar2(20) TYPE INDEX BY BINARY_INTEGER;

declare  
    v_f1  T_F1;
begin

   SELECT T1.F1 BULK COLLECT into  v_f1  FROM T1 WHERE  T1.F2='2009';

    forall i in v_f1  .first .. v_f1  .last
          update T2 set  ... where T2.F1 = v_f1(i);

    forall i in v_f1  .first .. v_f1  .last
          update T3 set  ... where T3.F1 = v_f1(i);

    forall i in v_f1  .first .. v_f1  .last
          update T4 set  ... where T4.F1 = v_f1(i);

end;

 

 (3)  游标,比如:

begin
  for rec in (SELECT T1.F1 FROM T1 WHERE  T1.F2='2009')
  loop
      update T2 set  ... where T2.F1 =rec.f1;
      update T3 set  ... where T2.F1 =rec.f1;
     update T3 set  ... where T2.F1 =rec.f1;
  end loop;

end;
-----

1.你这个forall 的方法和我直接用游标,那个效率更高
2.循环插入的时候,你用的forall应该比for 效率高,这个我也挺过别人说过;但是我想不都是一条条的处理吗?能有多大区别?

(4)

你这个forall 的方法和我直接用游标,那个效率更高

下面我来给你实证一下:

SQL> create table tobj as select * from all_objects;

Table created

SQL> create index idx_tobj on tobj(object_id);

Index created


scott@O9I.US.ORACLE.COM> alter session set sql_trace=true;

会话已更改。

scott@O9I.US.ORACLE.COM> set timing on
scott@O9I.US.ORACLE.COM> begin
  2     for c in (SELECT object_id FROM tobj) loop
  3            update tobj set object_name = 'New_' || substrb(object_name, 1, 2
5) where object_id = c.object_id;
  4     end loop;
  5  end;
  6  /

PL/SQL 过程已成功完成。

已用时间:  00: 00: 06.02
scott@O9I.US.ORACLE.COM> alter session set sql_trace=false;
会话已更改。


scott@O9I.US.ORACLE.COM> alter session set sql_trace=true;

会话已更改。

已用时间:  00: 00: 00.00
scott@O9I.US.ORACLE.COM> declare
  2     TYPE t_nums IS TABLE OF number;
  3     ids t_nums;
  4  begin
  5     SELECT object_id BULK COLLECT into  ids  FROM tobj;
  6      forall i in ids.first .. ids.last
  7            update tobj set object_name = 'New_' || substrb(object_name, 1, 2
5) where object_id = ids(i);
  8  end;
  9  /

PL/SQL 过程已成功完成。

已用时间:  00: 00: 03.08
scott@O9I.US.ORACLE.COM> alter session set sql_trace=false;

会话已更改。



下面看tkprof结果中的关键部分:

第一个方法(cursor):

UPDATE tobj set object_name = 'New_' || substrb(object_name, 1, 25)
where
object_id = :b1


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute  38102      1.98       2.67          0      76569      40221       38102
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total    38103      1.98       2.67          0      76569      40221       38102

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 59     (recursive depth: 1)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  UPDATE  (cr=76581 r=0 w=0 time=1907615 us)
  38102   INDEX RANGE SCAN IDX_TOBJ (cr=76287 r=0 w=0 time=466460 us)(object id 75110)



第二个方法(for all):

UPDATE tobj set object_name = 'New_' || substrb(object_name, 1, 25)
where
object_id = :b1


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      1.53       3.34          0      38190      39786       38102
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      1.53       3.34          0      38190      39786       38102

Misses in library cache during parse: 0
Optimizer goal: CHOOSE
Parsing user id: 59     (recursive depth: 1)

Rows     Row Source Operation
-------  ---------------------------------------------------
      0  UPDATE  (cr=38199 r=0 w=0 time=3109225 us)
  38102   INDEX RANGE SCAN IDX_TOBJ (cr=38187 r=0 w=0 time=382925 us)(object id 75110)


分享到:
评论

相关推荐

    记录 集合 BULK COLLECT FORALL 执行计划

    在PL/SQL编程环境中,集合操作BULK COLLECT和FORALL是提高数据库处理效率的关键特性。它们主要用于批量处理数据,减少数据库调用次数,从而优化性能。这些特性尤其适用于处理大量数据时,如循环遍历结果集并进行更新...

    Oracle 中使用 fetch bulk collect into 批量效率的读取游标数据

    下面我们通过实际的例子来说明它的使用,并与逐条取记录的 fetch into 执行效率上进行比较。测试环境是 Oracle 10g 10.2.1.0,查询的联系人表 sr_contacts 中有记录数 1802983 条,游标中以 rownum 限定返回的记录数...

    oracle批量处理(bulk collect)

    这个例子展示了如何使用`BULK COLLECT`一次性加载最多100行的薪水数据,以及通过采样获取大约10%的数据。 ##### 2. 在FETCH INTO中使用BULK COLLECT ```plsql DECLARE TYPE dept_rec_tab IS TABLE OF dept%...

    bulk collect学习

    另外,与 Bulk Collect 相关的还有 FORALL 语句,它用于执行批处理操作,如批量插入、删除和更新。FORALL 可以配合 INTO 集合一起使用,以高效地处理大量数据,尤其是在执行数据迁移或批量更新等操作时。 总结来说...

    使用BULK COLLECT, MERGE 语句提高sql执行效率

    详细介绍了使用 BULK COLLECT 进行批量操作 提高sql的执行效率 使用MERGE INTO USING 一条sql搞定 新增和修改 使用connect by 进行递归树查询

    bulk collect 使用实例

    结合一个存储过程的实例,介绍了 bulk collect 的使用

    浅谈PL/SQL批处理语句:BULK COLLECT与FORALL对优化做出的贡献

    本文主要讨论了两个核心的批处理特性:BULK COLLECT 和 FORALL,它们对于优化PL/SQL程序的效率有着显著的贡献。 BULK COLLECT 是一个用于加速查询的特性,它允许一次性地将查询结果集加载到集合(collections)中,...

    oracle bulk collect

    根据提供的文件信息,我们可以深入探讨Oracle中的`BULK COLLECT`功能及其在实际场景中的应用。这段代码示例虽然较为杂乱,但可以提炼出的关键点主要包括:如何使用`BULK COLLECT`来提高查询效率、如何声明和使用表...

    sal,ename BULK COLLECT INTO

    #### 三、BULK COLLECT INTO 的语法与用法 **基本语法格式:** ```sql DECLARE CURSOR cursor_name IS SELECT column_list FROM table_or_view WHERE condition; type_type TYPE IS TABLE OF column_name%...

    for all 用法小结

    在这个例子中,`FOR` 循环为每一条记录单独执行一个插入操作,而 `FORALL` 则将所有的插入操作捆绑成一个单一的操作。通过比较两者的执行时间,可以看出 `FORALL` 的性能优势。 #### 五、注意事项 - 使用 `FORALL`...

    oracle下巧用bulk collect实现cursor批量fetch的sql语句

    Bulk Collect 提升性能的关键在于减少了数据库与PL/SQL引擎之间的交互次数。传统的逐行Fetch方式,每次从Cursor获取一行数据都会涉及一次系统调用,而Bulk Collect则将多次调用合并为一次,显著降低了I/O开销。 在...

    Oracle BULK COLLECT批量取数据解决方法

    在Oracle数据库中,BULK COLLECT 还可以与其他操作结合使用,如BULK INSERT用于批量插入数据,或者与FORALL一起使用,进行批量更新或删除。这些技术通常在处理大数据量时,能显著提升应用程序的性能,并减少资源消耗...

    Oracle批量查询、删除、更新使用BULK COLLECT提高效率

    Oracle数据库提供了一种高效的方法来处理批量操作,如查询、删除和更新,这就是BULK COLLECT和数组集合类型的使用。BULK COLLECT是PL/SQL中的一个关键字,它允许我们一次性收集多行数据,而不是逐行处理,从而显著...

    forall 用法小结

    最后,比较两次插入操作的执行时间,可以明显看出`FORALL`循环在执行相同任务时,耗时远低于传统的`FOR`循环,充分证明了批量绑定对于提升性能的有效性。 #### 结论 综上所述,`FORALL`语句在Oracle数据库中提供了...

    Oracle 遍历游标的四种方式汇总(for、fetch、while、BULK COLLECT)

    在Oracle数据库中,遍历游标是处理查询结果集的一种常见方法,特别是在编写存储过程或PL/...而BULK COLLECT和FORALL则针对大数据量操作优化了性能。根据实际需求,选择合适的遍历方式能有效提升代码的效率和可维护性。

    abap collect的用法与实例

    在ABAP编程中,`collect`关键字用于对内表中的数据进行分类聚合,通常用于统计特定列的数值。本篇文章将详细介绍`collect`的用法并提供实例。 首先,理解`collect`的基本概念。`collect`操作是基于一个或多个关键列...

Global site tag (gtag.js) - Google Analytics