Re: Consulta Eficiente

From: Rodriguez Fernando <rodriguez(at)ort(dot)edu(dot)uy>
To: Rafa Comino <rafacomino(at)gmail(dot)com>
Cc: postgres Emanuel CALVO FRANCO <postgres(dot)arg(at)gmail(dot)com>, pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Consulta Eficiente
Date: 2008-10-20 10:22:54
Message-ID: 48FC5BFE.2010103@ort.edu.uy
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

Rafa Comino escribió:
>
> DECLARE
> curpet CURSOR (fechaI DATE, fechaF DATE) FOR
> SELECT isbn, identidad, idpeticion, fechapeticion
> FROM peticiones
> WHERE fechapeticion >= fechaI
> AND fechapeticion <= fechaF
> AND tipopeticion = 'PC'
> AND completa = true
> ORDER BY fechapeticion;
>
> ....
>
> BEGIN
> .....
> -- AQUI BORRO LOS 500.000 Registros, aunque creo q estos no son
> el problema principal
> DELETE FROM peticiones
> WHERE fechapeticion >= ldt_fini
> AND fechapeticion < ldt_ffin
> AND (completa != true OR tipopeticion != 'PC');
>
> -- Aquí abro el cursor que me devuelve unas 200.000 filas y que
> tengo que tratar una a una
> OPEN curpet(ldt_fini, ldt_ffin);
> -- Saco el primer registro
> FETCH curpet INTO lr_pet;
> WHILE FOUND LOOP
> IF ((SELECT COUNT(*) FROM log_peticiones WHERE isbn =
> lr_pet.isbn AND identidad = lr_pet.identidad AND tipopeticion='PC' AND
> fechapeticion >= ldt_fechanocobrar) > 0) THEN
> DELETE FROM peticiones WHERE idpeticion = lr_pet.idpeticion;
> ELSE
> -- Elimino las peticiones repetidas mayores que la
> petición que estoy revisando
> DELETE FROM peticiones
> WHERE isbn = lr_pet.isbn
> AND identidad = lr_pet.identidad
> AND tipopeticion='PC'
> AND fechapeticion >= ldt_fini
> AND fechapeticion <= ldt_ffin
> AND fechapeticion > lr_pet.fechapeticion;
> END IF;
>
> FETCH curpet INTO lr_pet;
> END LOOP;
> -- Cierro el cursor
> CLOSE curpet;
>
> ...
>
> INSERT INTO log_peticiones(tipopeticion, identidad, isbn,
> fechapeticion)
> SELECT tipopeticion, identidad, isbn, fechapeticion
> FROM peticiones
> WHERE fechapeticion >= ldt_fini
> AND fechapeticion < ldt_ffin;
> ....
>
> No se si estoy equivocado o no, pero yo el principal problema que veo
> es que al ejecturarse la función con toda esta cantidad de
> inserciones, modificación, eliminacíones y consultas, se hacer una
> transacción muy grande y ralentiza todo ¿qué opináis? aunque tampoco
> veo que sean tanta cantidad de registros.
>
>
>
>
> 2008/10/17 postgres Emanuel CALVO FRANCO <postgres(dot)arg(at)gmail(dot)com
> <mailto:postgres(dot)arg(at)gmail(dot)com>>
>
> Podrias compartir la parte del codigo afectada?
>
> El día 17 de octubre de 2008 10:08, postgres Emanuel CALVO FRANCO
> <postgres(dot)arg(at)gmail(dot)com <mailto:postgres(dot)arg(at)gmail(dot)com>> escribió:
> > Lo que podes hacer es ejecutar la consulta por partes (con limits) y
> > ahacer cursores para cada consulta.
> > Es mas laborioso pero ocuparias menos memoria.
> >
> >
> >
> > El día 17 de octubre de 2008 9:27, Silvio Quadri
> <silvioq(at)gmail(dot)com <mailto:silvioq(at)gmail(dot)com>> escribió:
> >>
> >>
> >> El 17 de octubre de 2008 4:32, Rafael Comino Mateos
> <ccomino(at)kaplan(dot)es <mailto:ccomino(at)kaplan(dot)es>>
> >> escribió:
> >>>
> >>> Tengo una función que al ejecutarse debe trabajar con un
> conjunto de
> >>> 1.000.000 de registros aproximadamente.
> >>>
> >>> Sobre ese conjunto de datos, en un cursor saco una a una las
> filas y la
> >>> mayoría las borro y otras pues las guardo en una tabla, o hago
> cálculos,
> >>> etc.
> >>>
> >>> El problema que tengo es de eficiencia, ya que la transacción
> se hace tan
> >>> grande que ocupa demasiada memoria y se hace lentísimo la
> ejecución.
> >>>
> >>> Que puedo hacer?
> >>
> >> ¿Es necesario que ejecutes todo en una transacción?
> >> ¿Es necesario también tener un cursor?
> >> Yo he ejecutado cosas similares con plpgsql y no tuve
> inconvenientes ...
> >>
> >> Después de ejecutar muchos "delete"s sobre la tabla ¿Hacés el
> vacuum?
> >> Quizás ejecuciones anteriores que no efectuaron el vacuum
> correspondiente
> >> estén afectando la performance.
> >>
> >> Saludos!
> >> Silvio
> >>
> >>
> >>
> >>
> >
> --
> TIP 10: no uses HTML en tu pregunta, seguro que quien responda no
> podrá leerlo
>
>
Hola, disculpa lo entreverada de la idea.
deberias reemplazar
IF ((SELECT COUNT(*) FROM log_peticiones WHERE isbn = lr_pet.isbn
AND identidad = lr_pet.identidad AND tipopeticion='PC' AND fechapeticion
>= ldt_fechanocobrar) > 0)

por

delete from log_peticiones WHERE
existis (
SELECT count(*), peticiones.id_peticion
from peticiones
where petiones.id_peticion = log_peticiones.id_peticion and
peticiones.isbn = log_peticiones.isbn and
peticiones.identidad = log_peticiones.identidad and
peticiones.tipo_peticion = log_peticiones.tipo_peticion
peticiones.fechapeticion >= fechaI AND
peticiones.fechapeticion <= fechaF AND
peticiones.tipopeticion = 'PC' and
peticiones.completa = true and
peticiones.fechapeticion >= ldt_fechanocobrar
group by peticiones.id_peticion
having count(*)> 0)

la idea es evitar que el cursor sea tan grande

tambien podes reemplazar el otro delete

delete from peticiones WHERE
not existis (
SELECT log_peticiones.id_peticion
from log_peticiones
where petiones.id_peticion = log_peticiones.id_peticion and
peticiones.isbn = log_peticiones.isbn and
peticiones.identidad = log_peticiones.identidad and
peticiones.tipo_peticion = log_peticiones.tipo_peticion
peticiones.fechapeticion >= fechaI AND
peticiones.fechapeticion <= fechaF AND
peticiones.tipopeticion = 'PC' and
peticiones.completa = true and
peticiones.fechapeticion >= ldt_fechanocobrar)

saludos Fernando

In response to

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Jaume Riu 2008-10-20 11:51:23 RE: Error configure plphp
Previous Message Jaime Casanova 2008-10-18 18:16:36 Re: RE: [pgsql-es-ayuda] Actualización de PostgreSQL me acabó con la BD