Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1180680
  • 博文数量: 398
  • 博客积分: 10110
  • 博客等级: 上将
  • 技术积分: 4055
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-23 20:01
个人简介

新博客http://www.cnblogs.com/zhjh256 欢迎访问

文章分类

全部博文(398)

文章存档

2012年(1)

2011年(41)

2010年(16)

2009年(98)

2008年(142)

2007年(100)

我的朋友

分类: Oracle

2008-01-06 21:25:45

PL/SQL程序调优七(使用NOCOPY优化器提示调整PL/SQL过程调用)

       默认情况下,OUTIN OUT参数通过值传递,IN OUT的值在子程序执行前被拷贝。在子程序执行期间,会有临时变量保存输出参数的值。如果子程序正常退出,它们的值将被拷贝到实际的参数,否则原始的参数不会被改变。

       当参数代表很大的结果集,如集合,记录,对象类型时,这些拷贝会比较慢并且使用很多内存。

       为了避免这种性能负载,可以声明NOCOPY,允许优化器通过引用传递OUTIN OUT参数的值。如果子程序正常退出,结果同默认的OUT/IN OUT。如果子程序非正常退出IN OUT参数的值仍然会改变。为了使用这种技术,必须确保所有的异常都被恰当处理了。如下:

DECLARE
  TYPE Staff IS VARRAY(200) OF Employee;
  PROCEDURE reorganize (v_staff IN OUT NOCOPY Staff) IS ...

       两者花费的时间如下:

DECLARE
   TYPE EmpTabTyp IS TABLE OF ITO_DATA_CENTER%ROWTYPE;
   emp_tab EmpTabTyp := EmpTabTyp(NULL);  -- initialize
   t1 NUMBER;
   t2 NUMBER;
   t3 NUMBER;
   PROCEDURE get_time (t OUT NUMBER) IS
     BEGIN t := DBMS_UTILITY.get_time; END;
   PROCEDURE do_nothing1 (tab IN OUT EmpTabTyp) IS
     BEGIN NULL; END;
   PROCEDURE do_nothing2 (tab IN OUT NOCOPY EmpTabTyp) IS
     BEGIN NULL; END;
BEGIN
   SELECT * INTO emp_tab(1) FROM ITO_DATA_CENTER WHERE ROWNUM=1;
   emp_tab.EXTEND(10000, 1);  -- copy element 1 into 2..50000
   get_time(t1);
   do_nothing1(emp_tab);  -- pass IN OUT parameter
   get_time(t2);
   do_nothing2(emp_tab);  -- pass IN OUT NOCOPY parameter
   get_time(t3);
   DBMS_OUTPUT.PUT_LINE('Call Duration (secs)');
   DBMS_OUTPUT.PUT_LINE('--------------------');
   DBMS_OUTPUT.PUT_LINE('Just IN OUT: ' || TO_CHAR((t2 - t1)/100.0));
   DBMS_OUTPUT.PUT_LINE('With NOCOPY: ' || TO_CHAR((t3 - t2))/100.0);
END;
/

Call Duration (secs)

--------------------

Just IN OUT: 1.35

With NOCOPY: 0

NOCOPY的限制

       需要注意,NOCOPY是一个提示,不是指示符。在以下情况下,PL/SQL不会使用NOCOPY提示,仍使用值传递:

       ·实际的参数是关联数组的一个元素,而不是整个关联数组。

       ·子程序通过数据库链接/外部过程调用;

       ·传递实际的参数需要隐示数据类型转换;

       ·实参和形参是纪录,实参声明为一个FOR循环中的一个索引,并且相应字段上的约束不同;

       ·实参和形参是纪录,但是其中一个或者两个都是通过%ROWTYPE%TYPE声明,但是约束不同;

       ·实参有约束,如精度要求或者NOT NULL。字符除外,并且该限制不包括集合的元素和组合类型的属性。

阅读(1129) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~