专栏首页杨建荣的学习笔记pl/sql中的forall简单测试(r5笔记第63天)

pl/sql中的forall简单测试(r5笔记第63天)

之前写过一篇bulk collect的博文,只是对于bulk collect做了简单的实例。http://blog.itpub.net/23718752/viewspace-1289696/ 其实不光是bulk collect,forall对于pl/sql的性能的提升也是相当大的。 可以参见下面的两个图,可以看到其实在pl/sql中,可能很多时候我们所写的pl/sql代码会在sql引擎和plsql引擎建进行上下文的切换,这个过程还是很耗费时间的。

而forall却是相反,是提供一次上下文切换,会在forall的过程中进行数据的包装处理。一次发送给sql执行器去处理,大大减少了上下文切换时间。

对于此,可以想象,如果cursor中的结果集很庞大,就很可能进行大量的上下文切换,导致执行速度骤降。 我们来做一个简单的实例来说明一下。 我们创建一个表test_data,里面大概有7万多的数据量。

n1@TEST11G> create table test_data as select *from all_objects;
Table created.

n1@TEST11G> select count(*)from test_data;
  COUNT(*)
----------
     71659
1 row selected

n1@TEST11G> create unique index inx_test_data_pk on test_data(object_id);
Index created.
Elapsed: 00:00:00.48

然后就开始执行存储过程

[ora11g@oel1 plsql]$ cat a.sql
create or replace procedure test_proc as  
  cursor test_cur is select *from test_data;
  i number;
begin
  i:=1;
  for cur in test_cur
   loop
   update test_data set object_name=cur.object_name
where object_id=cur.object_id;
   dbms_output.put_line('this is a test');
   i:=i+1;
   end loop;
end;
/

exec test_proc;

执行的过程中会看到进程占用了大量的cpu资源。可见进行了大量的上下文切换。其实一个主要的信息点就是可以看到输出了大量的日志内容,最后还因为缓存的原因退出了。

......
this is a test
this is a test
this is a test
this is a test
this is a test
this is a test
this is a test
this is a test
this is a test
this is a test
this is a test
this is a test
this is a test
this is a test
this is a test
BEGIN test_proc; END;

*
ERROR at line 1:
ORA-20000: ORU-10027: buffer overflow, limit of 1000000 bytes
ORA-06512: at "SYS.DBMS_OUTPUT", line 32
ORA-06512: at "SYS.DBMS_OUTPUT", line 97
ORA-06512: at "SYS.DBMS_OUTPUT", line 112
ORA-06512: at "N1.TEST_PROC", line 10
ORA-06512: at line 1

Elapsed: 00:00:13.73 同样的要求,如果使用forall的形式,使用的代码如下。

[ora11g@oel1 plsql]$ cat b.sql
create or replace procedure test_proc as  
  cursor test_cur is select *from test_data;
  type rec_type is table of test_cur%rowtype index by binary_integer;
  recs rec_type;
begin
  open test_cur;
  fetch test_cur bulk collect into recs;
  close test_cur;
  forall i in 1..recs.COUNT
   update test_data set object_name=recs(i).object_name
where object_id=recs(i).object_id;
   dbms_output.put_line('this is a test');
end;
/

这种效果就好得多,可以看到日志中只输出了一次日志信息,意味着只进行了一次上下文切换,这种方法明显要好很多。

n1@TEST11G> exec test_proc;
this is a test
PL/SQL procedure successfully completed.
Elapsed: 00:00:01.67

对于大批量的数据处理还是很值得推荐的。后续会使用dbms_profiler来对此测试一下,可以看出在一些实现点中还是存在着很大的不同。

本文分享自微信公众号 - 杨建荣的学习笔记(jianrong-notes),作者:r5笔记第63天

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2015-06-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 由drop datafile导致的oracle bug(r6笔记第56天)

    今天碰到了一个dataguard在10gR2的bug,不管怎么样确实是在特定的时间做了特定的操作结果碰到了特定的问题。 这个问题是在10gR2的版本10.2.0...

    jeanron100
  • MySQL误操作数据恢复的简单实践(r11笔记第67天)

    前几天有个同事碰到了一个MySQL数据恢复的问题,他运行了一条update语句,结果忘记了加where条件,结果等反应过来已经晚了。我简单确认了下,是否...

    jeanron100
  • MySQL备份恢复第一篇(r5笔记第5天)

    今天学习了下MySQL的备份恢复内容,也算是对之前的 数据导入导出的一个细化内容。备份恢复的内容其实还是蛮复杂的,一般网站上提到的备份恢复也基本都是逻辑备份恢复...

    jeanron100
  • 在64位机上编译,运行一个多线程程序出现的libgcc_s.so.1的问题的解决

    起初编译的时候是这样的 gcc test.c -o test -lpthread 然后运行test的时候提示如下错误 libgcc_s.so.1 ...

    用户3765803
  • Linux下查看压缩文件内容的 10 种方法

    通常来说,我们查看归档或压缩文件的内容,需要先进行解压缩,然后再查看,比较麻烦。今天给大家介绍 10 不同方法,能够让你轻松地在未解压缩的情况下查看归档或压缩文...

    心莱科技雪雁
  • logstash配置output到exec

    场景 监控文件内容发送告警 配置 input { stdin { type => 'demo-stdin' ...

    苦咖啡
  • docker 挂载文件不同步问题记录

    今天上午开发给我反应一个问题,所在宿主机上更改了挂载的文件在 docker 里面看不到改变,问我是不是 docker 启动的时候挂载的时候有问题,我说不可能啊,...

    张琳兮
  • docker 挂载文件不同步问题记录

    今天上午开发给我反应一个问题,所在宿主机上更改了挂载的文件在 docker 里面看不到改变,问我是不是 docker 启动的时候挂载的时候有问题,我说不可能啊,...

    张琳兮
  • 0631-6.2-如何确认一个Parquet文件是否被压缩

    1.使用Hive的desc命令查看Parquet表hive_table_test_parquet的底层文件格式是否被压缩。

    Fayson
  • synchronized锁住的是代码还是对象

    在Java中,synchronized关键字是用来控制线程同步的,就是在多线程的环境下,控制synchronized代码段不被多个线程同时执行。synchron...

    用户1205080

扫码关注云+社区

领取腾讯云代金券