Discussion:
Duda entre refcursor y record
Lazáro Rubén García Martínez
2012-07-04 23:24:14 UTC
Permalink
Hola a todos en la lista, necesito desarrollar un conjunto de funciones que serán ejecutadas desde PHP. Mi duda es la siguiente.

Para retornar un conjunto de datos, que debería ser más óptimo, utilizar un refcursor, o utilizar variables de salida (OUT) y retornar el resultado dentro de un For Loop?

Algo como esto:

Utilizando cursor:

CREATE OR REPLACE FUNCTION public.fun_listar_escuela (
)
RETURNS pg_catalog.refcursor AS
$body$
DECLARE
cursor_salida refcursor;
BEGIN
open cursor_salida FOR SELECT * FROM escuela;
RETURN cursor_salida;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;

Utilizando record:

CREATE OR REPLACE FUNCTION public.fun_listar_escuela (
out id_escuela integer,
out nombre varchar,
out escuela_relacionada integer
)
RETURNS SETOF record AS
$body$
DECLARE
tmp record;
BEGIN
FOR tmp IN SELECT * FROM escuela
Loop
id_escuela = tmp.id_escuela;
nombre = tmp.nombre;
escuela_relacionada = tmp.escuela_relacionada;
RETURN NEXT;
END Loop;
RETURN;
END;
$body$
LANGUAGE 'plpgsql';

Atento a sus recomendaciones.
Saludos.

Fin a la injusticia, LIBERTAD AHORA A NUESTROS CINCO COMPATRIOTAS QUE SE ENCUENTRAN INJUSTAMENTE EN PRISIONES DE LOS EEUU!
http://www.antiterroristas.cu
http://justiciaparaloscinco.wordpress.com
-
Enviado a la lista de correo pgsql-es-ayuda (pgsql-es-ayuda-RDL/***@public.gmane.org)
Para cambiar tu suscripción:
http://www.postgresql.org/mailpref/pgsql-es-ayuda
Alvaro Herrera
2012-07-05 04:01:59 UTC
Permalink
Post by Lazáro Rubén García Martínez
Hola a todos en la lista, necesito desarrollar un conjunto de funciones que serán ejecutadas desde PHP. Mi duda es la siguiente.
Para retornar un conjunto de datos, que debería ser más óptimo, utilizar un refcursor, o utilizar variables de salida (OUT) y retornar el resultado dentro de un For Loop?
Depende de si quien llama a la función leerá todo el resultado o sólo
una parte. Si es sólo una parte, el refcursor gana porque no ejecuta
toda la consulta sino sólo la parte que es leída. Si lo lee todo, igual
gana el refcursor, porque de la otra manera hay que crear un tuplestore
con el resultado. Pero desde el punto de vista de la mantenabilidad
(¿? sorry, es tarde), la variables OUT son mucho más claras en el código
de la aplicación que leer desde un cursor.
--
Álvaro Herrera <alvherre-s8A4EuBfO+***@public.gmane.org>
-
Enviado a la lista de correo pgsql-es-ayuda (pgsql-es-ayuda-RDL/***@public.gmane.org)
Para cambiar tu suscripci�n:
http://www.postgresql.org/mailpref/pgsql-es-ayuda
Lazáro Rubén García Martínez
2012-07-05 13:47:46 UTC
Permalink
Alvaro muchas gracias por tu respusta, ahora te pregunto, si en vez de retornar los valores de la consulta utilizando un For Loop, lo hago utilizando un RETURN QUERY obtendría alguna ventaja, o sucedería lo mismo que si realizo un For Loop, me refiero a si con esta otra via también hay que crear un tuplestore con el resultado. (El tuplestore es la variable que se recorre en el ciclo no??)

La consulta quedaría de esta forma:

CREATE OR REPLACE FUNCTION public.fun_listar_escuela (
out id_escuela integer,
out nombre varchar,
out escuela_relacionada integer
)
RETURNS SETOF record AS
$body$
DECLARE
tmp record;
BEGIN
RETURN QUERY SELECT escuela.id_escuela, escuela.nombre, escuela.escuela_relacionada
FROM escuela;
END;
$body$
LANGUAGE 'plpgsql';


Atento a tus recomendaciones.
Saludos.

________________________________________
From: Alvaro Herrera [alvherre-s8A4EuBfO+***@public.gmane.org]
Sent: Wednesday, July 04, 2012 11:31 PM
To: Lazáro Rubén García Martínez
Cc: Ayuda
Subject: Re: [pgsql-es-ayuda] Duda entre refcursor y record
Post by Lazáro Rubén García Martínez
Hola a todos en la lista, necesito desarrollar un conjunto de funciones que serán ejecutadas desde PHP. Mi duda es la siguiente.
Para retornar un conjunto de datos, que debería ser más óptimo, utilizar un refcursor, o utilizar variables de salida (OUT) y retornar el resultado dentro de un For Loop?
Depende de si quien llama a la función leerá todo el resultado o sólo
una parte. Si es sólo una parte, el refcursor gana porque no ejecuta
toda la consulta sino sólo la parte que es leída. Si lo lee todo, igual
gana el refcursor, porque de la otra manera hay que crear un tuplestore
con el resultado. Pero desde el punto de vista de la mantenabilidad
(¿? sorry, es tarde), la variables OUT son mucho más claras en el código
de la aplicación que leer desde un cursor.

--
Álvaro Herrera <alvherre-s8A4EuBfO+***@public.gmane.org>

Fin a la injusticia, LIBERTAD AHORA A NUESTROS CINCO COMPATRIOTAS QUE SE ENCUENTRAN INJUSTAMENTE EN PRISIONES DE LOS EEUU!
http://www.antiterroristas.cu
http://justiciaparaloscinco.wordpress.com

Fin a la injusticia, LIBERTAD AHORA A NUESTROS CINCO COMPATRIOTAS QUE SE ENCUENTRAN INJUSTAMENTE EN PRISIONES DE LOS EEUU!
http://www.antiterroristas.cu
http://justiciaparaloscinco.wordpress.com
-
Enviado a la lista de correo pgsql-es-ayuda (pgsql-es-ayuda-RDL/***@public.gmane.org)
Para cambiar tu suscripción:
http://www.postgresql.org/mailpref/pgsql-es-ayuda
Alvaro Herrera
2012-07-05 14:42:28 UTC
Permalink
Post by Lazáro Rubén García Martínez
Alvaro muchas gracias por tu respusta, ahora te pregunto, si en vez de retornar los valores de la consulta utilizando un For Loop, lo hago utilizando un RETURN QUERY obtendría alguna ventaja, o sucedería lo mismo que si realizo un For Loop, me refiero a si con esta otra via también hay que crear un tuplestore con el resultado. (El tuplestore es la variable que se recorre en el ciclo no??)
No estoy seguro pero me parece que es exactamente lo mismo, porque
ppgsql sólo opera de esa forma. (Un tuplestore es un almacén de tuplas.
Recibe todas las tuplas del ciclo o la consulta completa, y cuando la
función termina, el tuplestore se lee tupla por tupla para retornar el
resultado).

¿Qué es lo que quieres optimizar? Porque la diferencia en tiempo entre
una cosa (refcursor) y la otra (variables OUT) debe ser minúscula.

Cuando usas refcursor también hay un tuplestore: el refcursor se guarda
en el tuplestore, y tu código debe abrir el tuplestore, leer el
resultado, y luego al recibir el FETCH empezarás a leer tuplas desde el
plan de ejecución. Nota que hay que hacer un FETCH, en cambio en la
otra solución lees los registros directamente. Toda esa complejidad
extra me hace pensar que no hay por donde perderse.
--
Álvaro Herrera <alvherre-s8A4EuBfO+***@public.gmane.org>
-
Enviado a la lista de correo pgsql-es-ayuda (pgsql-es-ayuda-RDL/***@public.gmane.org)
Para cambiar tu suscripci�n:
http://www.postgresql.org/mailpref/pgsql-es-ayuda
Lazáro Rubén García Martínez
2012-07-05 16:52:22 UTC
Permalink
El tema es que tengo par de funciones que utilizan cursores y son ejecutadas desde PHP, el códifgo utilizado desde PHP es el sigueinte:

function _execute_sql_cursor($query){

$sql = db_query($query);

db_query('COMMIT');

return $sql;

}

donde query puede ser algo como esto:

$query = "BEGIN; SELECT * from miFuncion('w'); FETCH ALL IN w;";

Obtengo el resultado del cursor en la variable $sql, y despues hago commit.

Pero me estaba sucediendo, que como utilizo pgpool-II, la primera parte se jecutaba en un nodo y el commit en otro, generando un error, que para postgres es un warning. En algún momento llegué a pensar que necesitaba reimplementar las funciones, y ahí la duda entre cursores y parametros OUT en cuanto a rendimiento, pero investigando encontré que al parecer esto era un bug, que había sido resuelto, instalé la nueva verión de pgpool-II y al parecer el problema se resolvió.


De todos modos, muchisimas gracias por tu ayuda, porque al final, lo que más vale es el nuevo conocimiento que uno va adquirirendo.

Nuevamente, gracias.

Saludos a todos.



________________________________________
From: Alvaro Herrera [alvherre-s8A4EuBfO+***@public.gmane.org]
Sent: Thursday, July 05, 2012 10:12 AM
To: Lazáro Rubén García Martínez
Cc: Ayuda
Subject: RE: [pgsql-es-ayuda] Duda entre refcursor y record
Post by Lazáro Rubén García Martínez
Alvaro muchas gracias por tu respusta, ahora te pregunto, si en vez de retornar los valores de la consulta utilizando un For Loop, lo hago utilizando un RETURN QUERY obtendría alguna ventaja, o sucedería lo mismo que si realizo un For Loop, me refiero a si con esta otra via también hay que crear un tuplestore con el resultado. (El tuplestore es la variable que se recorre en el ciclo no??)
No estoy seguro pero me parece que es exactamente lo mismo, porque
ppgsql sólo opera de esa forma. (Un tuplestore es un almacén de tuplas.
Recibe todas las tuplas del ciclo o la consulta completa, y cuando la
función termina, el tuplestore se lee tupla por tupla para retornar el
resultado).

¿Qué es lo que quieres optimizar? Porque la diferencia en tiempo entre
una cosa (refcursor) y la otra (variables OUT) debe ser minúscula.

Cuando usas refcursor también hay un tuplestore: el refcursor se guarda
en el tuplestore, y tu código debe abrir el tuplestore, leer el
resultado, y luego al recibir el FETCH empezarás a leer tuplas desde el
plan de ejecución. Nota que hay que hacer un FETCH, en cambio en la
otra solución lees los registros directamente. Toda esa complejidad
extra me hace pensar que no hay por donde perderse.

--
Álvaro Herrera <alvherre-s8A4EuBfO+***@public.gmane.org>

Fin a la injusticia, LIBERTAD AHORA A NUESTROS CINCO COMPATRIOTAS QUE SE ENCUENTRAN INJUSTAMENTE EN PRISIONES DE LOS EEUU!
http://www.antiterroristas.cu
http://justiciaparaloscinco.wordpress.com

Fin a la injusticia, LIBERTAD AHORA A NUESTROS CINCO COMPATRIOTAS QUE SE ENCUENTRAN INJUSTAMENTE EN PRISIONES DE LOS EEUU!
http://www.antiterroristas.cu
http://justiciaparaloscinco.wordpress.com
-
Enviado a la lista de correo pgsql-es-ayuda (pgsql-es-ayuda-RDL/***@public.gmane.org)
Para cambiar tu suscripción:
http://www.postgresql.org/mailpref/pgsql-es-ayuda
Alvaro Herrera
2012-07-05 22:16:58 UTC
Permalink
Post by Lazáro Rubén García Martínez
Pero me estaba sucediendo, que como utilizo pgpool-II, la primera parte se jecutaba en un nodo y el commit en otro, generando un error, que para postgres es un warning. En algún momento llegué a pensar que necesitaba reimplementar las funciones, y ahí la duda entre cursores y parametros OUT en cuanto a rendimiento, pero investigando encontré que al parecer esto era un bug, que había sido resuelto, instalé la nueva verión de pgpool-II y al parecer el problema se resolvió.
Uy. Ese es un bug harto serio.
--
Álvaro Herrera <alvherre-s8A4EuBfO+***@public.gmane.org>
-
Enviado a la lista de correo pgsql-es-ayuda (pgsql-es-ayuda-RDL/***@public.gmane.org)
Para cambiar tu suscripci�n:
http://www.postgresql.org/mailpref/pgsql-es-ayuda
Loading...