使用 Oracle PL/SQL NOCOPY 提示
参考文献:
official document: http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/tuning.htm#LNPLS01208
oracle nocopy hint tips: http://www.dba-oracle.com/plsql/t_plsql_nocopy_hint.htm
http://www.dba-oracle.com/t_pl_sql_nocopy_data_structures.htm
一 概念介绍:
PLSQL运行引擎在存储过程和函数之间传参有2种方法:传值和传引用
默认情况,OUT和IN OUT参数通过传值方式传递,IN参数是传引用方式。程序执行前IN OUT参数的实际值将被复制给形参。程序执行中间,临时变量保存参数的输出值。如果程序正常退出,这些值将被复制回原参数。如果程序异常退出,那么原参数值将不会改变。当IN OUT参数为大数据结构,诸如:集合、记录、对象类型实例时,通过传值方式的COPY动作将会导致程序执行速度下降,使用内存量上升。尤其是该程序被多次调用时更是如此。
为避免此类情况,我们可以指定NOCOPY暗示,告诉PLSQL编译器通过传引用方式传递OUT 和IN OUT参数。这样,形参将不会COPY参数实际值,也就是说形参和ACTUAL VALUE指向同一内存地址(memory location)。以此提高程序执行性能。
下面通过一段脚本对比一下,传值和传引用在程序执行性能上的差异:
二 示例对比:
nocopy.sql
SET SERVEROUTPUT ON
DECLARE
TYPE t_tab IS TABLE OF VARCHAR2(32767);
l_tab t_tab := t_tab();
l_start NUMBER;
PROCEDURE in_out (p_tab IN OUT t_tab) IS
BEGIN
NULL;
END;
PROCEDURE in_out_nocopy (p_tab IN OUT NOCOPY t_tab) IS
BEGIN
NULL;
END;
BEGIN
l_tab.extend;
l_tab(1) := '1234567890123456789012345678901234567890';
l_tab.extend(999999, 1); -- Copy element 1 into 2..1000000
-- Time normal IN OUT
l_start := DBMS_UTILITY.get_time;
in_out(l_tab);
DBMS_OUTPUT.put_line('IN OUT : ' ||
(DBMS_UTILITY.get_time - l_start));
-- Time IN OUT NOCOPY
l_start := DBMS_UTILITY.get_time;
in_out_nocopy(l_tab); -- pass IN OUT NOCOPY parameter
DBMS_OUTPUT.put_line('IN OUT NOCOPY: ' ||
(DBMS_UTILITY.get_time - l_start));
END;
/
SQL> @nocopy.sql
IN OUT :43
IN OUT NOCOPY: 0
PL/SQL procedure successfully completed.
三 使用NOCOPY限制:
1、如果实参为整个关联数组则该限制不起作用。
2、实参被强制指定精度,比例或not null时,该限制将不适用按最大长度强制的字符串参数。
3、实参和形参都是记录类型,二者存在以隐式方式或使用了%ROWTYPE类型声明时,作用在对应字段的强制说明不一制。
4、传递实参需要隐式类型转换时。
5、子程序涉及到远程调用(RPC---database link oras an external procedure)。
四 关于使用NOCOPY过程中的异常处理
虽说NOCOPY带来了性能上的优势,但是不容忽略的一点是当我们调用的子程序(带有NOCOPY提示)发生异常时,一旦处理不当很容易造成实参被修改。这是我们不愿看到的。下面引用官方的一段话并结合newkid大师的例子给予说明,详细请见ITPUB版:
http://www.itpub.net/thread-1147041-1-1.html
If the subprogram exits early with an exception, the values of OUT and IN OUT parameters (or object attributes) might still change. To use this technique, ensure that the subprogram handles all exceptions.
CREATE OR REPLACE PROCEDURE p_nocopy_test(p_id OUT NOCOPY NUMBER)
AS
BEGIN
p_id := 1;
raise_application_error(-20201,'NULL'); --程序终止
p_id := 2;
RETURN;
END;
/
DECLARE
v_id NUMBER := 0;
BEGIN
dbms_output.put_line('Before call p_nocopy_test: '||v_id);
p_nocopy_test(v_id);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('After call p_nocopy_test: '||v_id);
END;
/
Before call p_nocopy_test: 0
After call p_nocopy_test: 1
再来看一下去掉NOCOPY参数的子程序调用在遇到异常时的表现:
Before call p_nocopy_test: 0
After call p_nocopy_test: 0
那么针对NOCOPY子程序的异常处理该如何做?Oracle前面说了应该在子程序内部捕捉处理掉异常,例如:
CREATE OR REPLACE PROCEDURE p_nocopy_test(p_id OUT NOCOPY NUMBER)
AS
BEGIN
p_id := 1;
raise_application_error(-20201,'NULL'); --程序终止
p_id := 2;
--RETURN;
EXCEPTION
WHEN OTHERS THEN
p_id := 0;
RETURN;
END;
/
DECLARE
v_id NUMBER := 0;
BEGIN
dbms_output.put_line('Before call p_nocopy_test: '||v_id);
p_nocopy_test(v_id);
/*
EXCEPTION
WHEN OTHERS THEN
*/
dbms_output.put_line('After call p_nocopy_test: '||v_id);
END;
/
Before call p_nocopy_test: 0
After call p_nocopy_test: 0
-------------------
Dylan presents.
使用 Oracle PL/SQL NOCOPY 提示的更多相关文章
- ORACLE PL/SQL编程详解
ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...
- [推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼、百战不殆)
原文:[推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼.百战不殆) [推荐]ORACLE PL/SQL编程之五: 异常错误处理(知已知彼.百战不殆) 继上三篇:ORACLE PL/S ...
- ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)
原文:ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!) ORACLE PL/SQL编程之六: 把过程与函数说透(穷追猛打,把根儿都拔起!) 继上篇:ORACLE P ...
- [推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆)
原文:[推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆) [推荐]ORACLE PL/SQL编程详解之三: PL/SQL流程控制语句(不给规则,不成方圆) ...
- [推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下)
原文:[推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下) [推荐]ORACLE PL/SQL编程详解之一: PL/SQL 程序设计简介(千里之行,始于足下 ...
- [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)
原文:[顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功) [顶]ORACLE PL/SQL编程详解之二: PL/SQL块结构和组成元素(为山九仞,岂一日 ...
- Oracle PL/SQL Articles
我是搬运工....http://www.oracle-base.com/articles/plsql/articles-plsql.php Oracle 8i Oracle 9i Oracle 10g ...
- ORACLE PL/SQL编程详解(转)
原帖地址:http://blog.csdn.net/chenjinping123/article/details/8737604 ORACLE PL/SQL编程详解 SQL语言只是访问.操作数据库的语 ...
- Oracle PL/SQL Developer 上传下载Excel
接到需求,Oracle数据库对Excel数据进行上传和下载,百度后没有很全的方案,整理搜到的资料,以备不时之需. 一.下载Oracle数据到Excel中. 下载数据到Excel在MSSql中很简单,直 ...
- [强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)
原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七: 程序包的创建与应用(聪明在于学习,天 ...
随机推荐
- 百度网盘(百度云)SVIP超级会员共享账号每日更新(2024.01.13)
一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...
- [转帖]加速拥抱支持开源生态 | OceanBase 开源版3.1.1正式发布
https://www.oceanbase.com/news/accelerated-embrace-and-support-of-open-source-ecosystem-oceanbase-op ...
- [转帖]ramfs、tmpfs、rootfs、ramdisk介绍
ramfs.tmpfs.rootfs.ramdisk介绍 bootleader--->kernel---->initrd(是xz.cpio.是ramfs的一种,主要是驱动和为了加载ro ...
- [转帖] 如何kill一条TCP连接?
https://www.cnblogs.com/codelogs/p/16838850.html 原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介# 如果你的程序写 ...
- [转帖]linux 批量修改文件格式
将Windows上的shell脚本拷贝到Linux时,脚本的编码格式还是docs,需要改成unix才可执行,在文件不多的情况下可以直接手动更改,但是在脚本文件比较多的时候,手动改起来就太麻烦了,此时就 ...
- [转帖]性能分析之TCP全连接队列占满问题分析及优化过程(转载)
https://www.cnblogs.com/wx170119/p/12068005.html 前言 在对一个挡板系统进行测试时,遇到一个由于TCP全连接队列被占满而影响系统性能的问题,这里记录下如 ...
- [转帖]Linux系统硬链接和软链接具体实例讲解(超详细)
简介 在 Linux 中,元数据中的 inode 号(inode 是文件元数据的一部分但其并不包含文件名,inode 号即索引节点号)才是文件的唯一标识而非文件名.文件名仅是为了方便人们的记忆和使用, ...
- 京东ES支持ZSTD压缩算法上线了:高性能,低成本 | 京东云技术团队
1 前言 在<ElasticSearch降本增效常见的方法>一文中曾提到过zstd压缩算法[1],一步一个脚印我们终于在京东ES上线支持了zstd:我觉得促使目标完成主要以下几点原因: ...
- echarts去掉y轴线、设置x轴线的颜色、x轴文字颜色
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- MacBook m2 笔记本 + k8s容器环境开发笔记
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 为最近两周在 MacBook m2 + k8s 容器环境的 ...