原文地址:https://blogs.oracle.com/opal/entry/converting_ref_cursor_to_pipe

REF CURSORs are common in Oracle's stored procedural language PL/SQL. They let you pass around a pointer to a set of query results.

However in PHP, PDO_OCI doesn't yet allow fetching from them. And fetching from REF CURSORS in OCI8 is not as fast as doing a normal query. This is because of two architectural decisions: OCI8 doesn't use the preferred Oracle style of "array fetching". Instead it uses "prefetching", but prefetching from REF CURSORS isn't supported by Oracle for various reasons (including that array fetching is available and recommended....)

One workaround, when you can't rewrite the PL/SQL code to do a normal query, is to write a wrapper function that pipes the output.

For this example, the "fixed" procedure that you can't change is:

create or replace procedure myproc(p1 out sys_refcursor) as
begin
open p1 for select last_name from employees;
end;

The wrapper function follows the performance tip in 12-14 of Tuning PL/SQL Applications for Performance and uses a BULK COLLECT:

create or replace package myplmap as
type outtype is record ( -- structure of the ref cursor in myproc
last_name varchar2()
);
type outtype_set is table of outtype;
function maprctopl return outtype_set pipelined;
end;
/
show errors create or replace package body myplmap as
function maprctopl return outtype_set pipelined is
outrow outtype_set;
p_rc sys_refcursor;
rlim pls_integer := ; -- fetch batches of rows at a time
begin
myproc(p_rc); -- call the original procedure
loop
fetch p_rc bulk collect into outrow limit rlim;
exit when outrow.count = ;
for i in .. outrow.count loop
pipe row (outrow(i));
end loop;
end loop;
end maprctopl;
end myplmap;

The PHP OCI8 code to query the pipelined function is:

<?php

$c = oci_connect('hr', 'hrpwd', '//localhost/XE');

$s = oci_parse($c, "select * from table(myplmap.maprctopl())");
oci_execute($s);
oci_fetch_all($s, $res);
var_dump($res); ?>

You could use this query in PDO_OCI too.

I found it doubled the performance of smallish tests with a local database (from small time to even smaller time). The change is more dramatic from a distant, remote database. With a query returning a large number of rows it dropped the runtime to 35 seconds from about 24 minutes.

This tip will appear in the next edition of the Underground PHP and Oracle Manual.

Update: Prefetching from REF CURSORS is supported in Oracle 11gR2. See Oracle Database 11gR2 Enhancements for PHP

Converting REF CURSOR to PIPE for Performance in PHP OCI8 and PDO_OCI的更多相关文章

  1. Report_报表中Ref Cursor数据源的概念和用法(案例)

    2014-06-22 Created By BaoXinjian

  2. REF CURSOR和CURSOR

    REF CURSOR DECLARE TYPE TY_EMP_CUR IS REF CURSOR; V_Emp_Cur TY_EMP_CUR; V_Id EMP.ID%TYPE; BEGIN OPEN ...

  3. Entity Framework 5.0.0 Function Import 以及 ODP. NET Implicit REF CURSOR Binding使用简介

    源代码 概要: 1,说明如何使用Entity Framework中的function import功能. 2,说明如何使用ODP.NET的隐式REF CURSOR绑定(implicit REF CUR ...

  4. Oracle ref cursor和sys_refcursor

    1. 自定义 ref cursor 和 sys_refcursor; 2. sys_refcursor 做为参数传递结果集; 3. ref cursor 做为参数传递结果集; 1. 自定义 ref c ...

  5. oracle中REF Cursor用法

    from:http://www.111cn.net/database/Oracle/42873.htm 1,什么是 REF游标 ? 动态关联结果集的临时对象.即在运行的时候动态决定执行查询. 2,RE ...

  6. PLSQL中显示Cursor、隐示Cursor、动态Ref Cursor差别

    一.显式cursor 显式是相对与隐式cursor而言的,就是有一个明白的声明的cursor.显式游标的声明类似例如以下(具体的语法參加plsql ref doc ): cursor cursor_n ...

  7. ORACLE中RECORD、VARRAY、TABLE、IS REF CURSOR 的使用及实例详解

    ORACLE中RECORD.VARRAY.TAB.IS REF CURSOR LE的使用及实例详解 create or replaceprocedure PRO_RECORD_ROW_TAB_EXAM ...

  8. oracle sys_refcursor用法和ref cursor区别

    --创建过程,参数为sys_refcursor,为out型 create or replace procedure aabbsys_refcursor(o out sys_refcursor) is ...

  9. oracle 存储过程及REF CURSOR的使用

    基本使用方法及示例 1.基本结构: CREATE OR REPLACE PROCEDURE 存储过程名字 (参数1 IN NUMBER,参数2 IN NUMBER) AS 变量1 INTEGER := ...

随机推荐

  1. [转]使用 ssh -R 穿透局域网访问内部服务器主机,反向代理 无人值守化

    原文: https://www.cnblogs.com/phpdragon/p/5314650.html ----------------------------------------------- ...

  2. 简单实现http proxy server怎么实现?

    原文:https://blog.csdn.net/dolphin98629/article/details/54599850 简单实现http proxy server怎么实现?

  3. Robotframework(2):创建RF第一条可执行的用例

    转载:http://www.cnblogs.com/CCGGAAG/p/7800323.html 上篇,我们说了如何配置基础的环境,配置好了python2.wxPython .robot framew ...

  4. 快速升级PHP5.4、MySql5.5版本WDCP面板一键包

    指定一键安装包环境升级PHP5.4版本 wget http://soft.sindns.net/wdcp/php_up54.sh sh php_up54.sh 直接登录SSH,下载和执行脚本自动会升级 ...

  5. Discuz! X3安装第三方主题出现:对不起,您安装的不是正版应用..的解决方法

    discuz 社区在更新到3.0以上后,增加了对插件的版本检测,在安装时,可能会出现:“对不起,您安装的不是正版应用,安装程序无法继续执行”的提示,要解决这个其实挺容易的,找到以下文件: /sourc ...

  6. CSDN博客QQ加群、微信

    对于QQ加群我一直是拒绝的,不是自己摆姿态,而是实在没有这种影响力和能力.然而今日一朋友的话改变了我这种想法,所以尝试在CSDN博客首页上增加QQ加群功能.此博客也就权当一个记录(主要是为了上传一张二 ...

  7. 【高德地图SDK】如何实现轨迹平滑移动?

    很多人应该都有类似的经历,叫完车,想看看车离我还有多远距离?但手机屏幕上的车不是一动不动,就是一跳一跳的漂移. 目前市面上大多产品“轨迹平滑移动”做的并不好. 市面上只有快的打车和一号专车实现了平滑移 ...

  8. iOS 设置 UIWebView UserAgent

    NSString *userAgent = [[[UIWebView alloc] init] stringByEvaluatingJavaScriptFromString:@"naviga ...

  9. LintCode: Happy Number

    C++ class Solution { public: /** * @param n an integer * @return true if this is a happy number or f ...

  10. vsphere 5.1 性能最佳实践。

    1.关于CPU负载.extop显示的结果 如果CPU load average>=1,说明主机过载了. 如果PCPU used%在80%左右说明良好,90%以上就临近过载了. VM赋予过多的vC ...