原文地址: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. Java-JUC(十):线程按序交替执行

    问题: 有a.b.c三个线程,使得它们按照abc依次执行10次. 实现: package com.dx.juc.test; import java.util.concurrent.locks.Cond ...

  2. 强制开启android webview debug模式使用Chrome inspect

    强制开启android webview debug模式使用Chrome inspect https://blog.csdn.net/zhulin2609/article/details/5143782 ...

  3. 数据库迁移工具Navicat Premium之OracleToMysql

    一.问题 由于工作需要,需要把业务库的数据库从oracle签到mysql,免费开源 二.解决办法 2.1:ETL单个对象进行转移(最笨的办法,所以抛弃掉了) 2.2:使用Navicat Premium ...

  4. Andriod NDK assets的三个相关知识

    如何获取assetManager   engine->app->activity->assetManager     Asset文件应该放在哪个目录? 如何生成tga文件: 可以用这 ...

  5. RedisTemplate 分页

    利用spring redis的RedisTemplate进行分页: 场景: 现有项目若干,根据项目的创建时间(createTime)进行降序读取: 存储结构: key:proList(list) 存放 ...

  6. Windows版Mycat结合mysql安装配置+水平切分(转载)

    来源:https://segmentfault.com/a/1190000009495748 参考文档:Mycat安装与使用 环境 环境 版本 windows 10 java 1.8.0 mysql ...

  7. listview下拉刷新 上拉(滑动分页)加载更多

    最 近做的类似于微博的项目中,有个Android功能要使用到listview的向下拉刷新来刷新最新消息,向上拉刷新(滑动分页)来加载更多.新浪微博就是使用这种方式的典型.当用户从网络上读取微博的时候, ...

  8. 手把手教你从零实现Linux misc设备驱动一(基于友善之臂4412开发板)

    关于怎样来写一个misc设备,在前面有篇文章已经介绍了大致的流程,如今就让我们来实现一个最简单的misc设备驱动. http://blog.csdn.net/morixinguan/article/d ...

  9. [转]一个简洁的 systemd 操作指南

    1.服务权限systemd有系统和用户区分:系统(/user/lib/systemd/system/).用户(/etc/lib/systemd/user/). 一般系统管理员手工创建的单元文件建议存放 ...

  10. 元素高度、宽度获取 style currentStyle getComputedStyle getBoundingClientRect

    1.示例代码 (1)html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...