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 <[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>>

    Podrias compartir la parte del codigo afectada?

    El día 17 de octubre de 2008 10:08, postgres Emanuel CALVO FRANCO
    <[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>> 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
    <[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>> escribió:
    >>
    >>
    >> El 17 de octubre de 2008 4:32, Rafael Comino Mateos
    <[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>>
    >> 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
--
TIP 10: no uses HTML en tu pregunta, seguro que quien responda no podrá leerlo

Responder a