oci_set_prefetch

(PHP 5, PECL OCI8 >= 1.1.0)

oci_set_prefetchEstablece el número de filas a precargar mediante consultas

Descripción

bool oci_set_prefetch ( resource $statement , int $rows )

Establece el número de filas que las bibliotecas de Oracle Client almacenará en búfer después de una llamada exitosa a oci_execute() y por cada petición de obtención interna subsigiente a la base de datos. Para consultas que devuelven un gran número de filas, se puede mejorar significativamente el rendimiento aumentando el número de precarga sobre el valor predeterminado de oci8.default_prefetch.

La precarga es la forma eficiente de Oracle de devolver más de una fila de datos desde la base de datos en cada petición de red. Esto puede resultar en un uso mejor de la red y la CPU. El almacenamiento en búder de filas es interno a OCI8 y el comportamiento de las funciones de obtención de OCI8 no se modifica a pesar del número de precargas. Por ejemplo, oci_fetch_row() siempre devolverá una fila. El almancenamiento en búfer de las precargas se realiza en base a cada sentencia y no es utilizado por sentencias reejecutadas o por otras conexiones.

Se ha de llamar a oci_set_prefetch() antes de invocar a oci_execute().

Un objetivo para el ajuste es establecer el valor de precarga a un tamaño razonable que pueda manejar la red y la base de datos. Para consultas que devuelven un número de filas muy grande, se podría mejorar la eficiencia total del sistema si las filas son obtenidas de la base de datos en varios trozos (esto es, establecer el valor de precarga menor que el número de filas). Esto permite que la base de datos maneje otras sentencias de usuarios mientras que el script de PHP está procesando el conjunto de filas actual.

La precarga de consultas se introdujo en Oracle 8i. La precarga de REF CURSOR se introdujo en Oracle 11gR2 y sucede cuando PHP está vinculado con las bibliotecas cliente de Oracle 11gR2 (o posterior). La precarga de cursores anidados fue introducida en Oracle 11gR2 y requiere que las bibliotecas de Oracle Client y las bases de datos sean la versión 11gR2 o posterior.

La precarga no está soportada cuando las consultas contienen columnas LONG o LOB. El valor de la precarga será ignorado y se usará la obtención de una única fila en todas las situaciones donde no esté soportada la precarga.

Al usar Oracle Database 12c, el valor precargado establecido por PHP puede ser sobrescrito por el fichero de configuración de del cliente oraaccess.xml de Oracle. Consulte la documentación de Oracle para más detalles.

Parámetros

statement

Un identificador de sentencia de OCI8 válido creado por oci_parse() y ejecutado por oci_execute(), o un identificador de sentencia de REF CURSOR.

rows

El número de filas que van a se precargadas, >= 0

Valores devueltos

Devuelve TRUE en caso de éxito o FALSE en caso de error.

Historial de cambios

Versión Descripción
5.3.2 (PECL OCI8 1.4) Antes de esta versión, rows debe ser >= 1.
5.3.0 (PECL OCI8 1.3.4) Antes de esta versión, la precarga estaba limitada al menor valor de rows filas y 1024 * rows bytes. La restricción del tamaño de bytes ahora ha sido eliminada.

Ejemplos

Ejemplo #1 Cambiar el valor de precarga predeterminado para una consulta

<?php

$conn 
oci_connect('hr''welcome''localhost/XE');

$stid oci_parse($conn'SELECT * FROM myverybigtable');
oci_set_prefetch($stid300);  // Establecer antes de llamar a oci_execute()
oci_execute($stid);

echo 
"<table border='1'>\n";
while (
$row oci_fetch_array($stidOCI_ASSOC+OCI_RETURN_NULLS)) {
    echo 
"<tr>\n";
    foreach (
$row as $item) {
        echo 
"    <td>".($item !== null htmlentities($itemENT_QUOTES) : "")."</td>\n";
    }
    echo 
"</tr>\n";
}
echo 
"</table>\n";

oci_free_statement($stid);
oci_close($conn);

?>

Ejemplo #2 Cambiar la precarga predeterminada para la obtención de un REF CURSOR

<?php
/*
  Crear el procedimiento almacenado PL/SQL:

  CREATE OR REPLACE PROCEDURE myproc(p1 OUT SYS_REFCURSOR) AS
  BEGIN
    OPEN p1 FOR SELECT * FROM all_objects WHERE ROWNUM < 5000;
  END;
*/

$conn oci_connect('hr''welcome''localhost/XE');

$stid oci_parse($conn'BEGIN myproc(:rc); END;');
$refcur oci_new_cursor($conn);
oci_bind_by_name($stid':rc'$refcur, -1OCI_B_CURSOR);
oci_execute($stid);

// Cambiar la precarga antes de ejecutar el cursor.
// La precarga de REF CURSOR funciona cuando PHP está vinculado con las bibliotecas cliente de Oracle 11gR2 o posteriores
oci_set_prefetch($refcur200);
oci_execute($refcur);

echo 
"<table border='1'>\n";
while (
$row oci_fetch_array($refcurOCI_ASSOC+OCI_RETURN_NULLS)) {
    echo 
"<tr>\n";
    foreach (
$row as $item) {
        echo 
"    <td>".($item !== null htmlentities($itemENT_QUOTES) : "")."</td>\n";
    }
    echo 
"</tr>\n";
}
echo 
"</table>\n";

oci_free_statement($refcur);
oci_free_statement($stid);
oci_close($conn);

?>

Si OCI8 de PHP realiza la obtención desde un REF CURSOR y luego pasa el REF CURSOR a un segundo procedimiento de PL/SQL para su procesamiento posterior, establezca el número de precargas de REF CURSOR a 0 para evitar que las filas se "pierdan" en el conjunto de resultados. El valor de la precarga es el número de filas extra obtenidas en cada petición interna de OCI8 para la base de datos, por lo que establecerlo a 0 significa que únicamente se obtiene una fila cada vez.

Ejemplo #3 Establecer el valor de precarga cuando se vuelve a pasar un REF CURSOR a Oracle

<?php

$conn 
oci_connect('hr''welcome''localhost/orcl');

// obtener el REF CURSOR
$stid oci_parse($conn'BEGIN myproc(:rc_out); END;');
$refcur oci_new_cursor($conn);
oci_bind_by_name($stid':rc_out'$refcur, -1OCI_B_CURSOR);
oci_execute($stid);

// Mostrar dos filas, pero no precargar ninguna fila extra, si no,
// esas filas extra no se pasarán de nuevo a myproc_use_rc().
// Un valor de precarga de 0 está permitido en PHP 5.3.2 y PECL OCI8 1.4
oci_set_prefetch($refcur0);
oci_execute($refcur);
$row oci_fetch_array($refcur);
var_dump($row);
$row oci_fetch_array($refcur);
var_dump($row);

// pasar el REF CURSOR a myproc_use_rc() para porcesar más datos
// con el conjunto de resultados
$stid oci_parse($conn'begin myproc_use_rc(:rc_in); end;'); 
oci_bind_by_name($stid':rc_in'$refcur, -1OCI_B_CURSOR);
oci_execute($stid);

?>

Ver también

add a note add a note

User Contributed Notes 1 note

up
1
bmichael at goldparrot dot com
11 years ago
If your are using Oracle's OCI libraries, on any project, which PHP does, you can use this limit.

I have done network level testing on the effect of this parameter.  It does improved efficiency.  Big Time.

Oracle uses SQL*Net as the transport mechanism for data between your connection and the database.  That is why you must setup Oracle properly.

This parameter tells SQL*NET to Buffer more results.  When SQL*NET (at the server) gets a request for data, it bundles up X rows (1,2,3,1000, etc) for transport.  It sends the appropriate SQL*NET headers back to the client, Waits for an ACK then begins sending data in MTU sized chunks (ethernet is something like 1500 bytes and ATM's WANS are around 1000 bytes).  The chunk size can also be tuned in SQL*NET, but with much less improvements.

TCP/IP then takes the data across the wire, breaking it up into multiple TCP/IP packets.

Once the exchange is done, the SQL*NET client sends an
ACK back to the SQL*NET Listener (the Oracle Server) and the transaction is complete.

Each round trip, SQL*NET looks up inside the server memory (UGA - user global area) to find the query results. It then grabs the rows necessary to send.  If it is one row, versus 1000 rows.  The process is the same.

There is much I could tell you on how the Database itself reacts.  If you can significantly lessen the amount of round trips you are making... WOW. 

For more info on Oracle OCI go to http://otn.oracle.com
To Top