Skip site navigation (1) Skip section navigation (2)

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 (view raw or flat)
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

pgsql-es-ayuda by date

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

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group