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