es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Los bucles PL/pgSQL no actualizan la marca de tiempo actual / now().

Quiero ver cuánto tiempo lleva cada iteración de un bucle dentro de un bloque DO en postgres. El diseño básico es el siguiente:

DO $$
declare v_time timestamptz;
declare i record;
begin
for i in select generate_series(1, 5) t
loop
select current_timestamp into v_time;
perform pg_sleep(i.t);
-- algo se hace aquí (pg_sleep para asegurar que pase algo de tiempo)
raise notice '%', v_time - (select current_timestamp);
-- se espera un intervalo negativo de RAISE
end loop;
end; $$;

Sin embargo, cuando ejecuto esto (he probado en Postgres 13 y 9), obtengo un intervalo de 0S:

NOTICE:  00:00:00
NOTICE:  00:00:00
NOTICE:  00:00:00
NOTICE:  00:00:00
NOTICE:  00:00:00
DO

La consulta se completó correctamente en 15 segundos y 389 milisegundos.

He hecho esto anteriormente y nunca me había encontrado con este problema, así que supongo que mi pregunta es “¿qué estoy haciendo mal esta vez?” en lugar de “¿por qué Postgres se comporta de manera inesperada?”.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Parece que el problema podría estar en el orden de ejecución de los comandos en el bloque DO. El current_timestamp se asigna a v_time antes de que se ejecute el comando pg_sleep, lo que significa que la diferencia calculada en la declaración raise notice es entre los mismos valores de marca de tiempo.

    Para ver cuánto tiempo tarda cada iteración de un bucle dentro de un bloque DO en PostgreSQL, es necesario modificar el código de la siguiente manera:

    DO $$
    declare 
        v_time timestamptz;
        i record;
    begin
        for i in select generate_series(1, 5) t
        loop
            select current_timestamp into v_time;
    
            -- se realiza algo aquí (pg_sleep para asegurar que pase algo de tiempo)
            perform pg_sleep(i.t);
    
            raise notice '%', (select current_timestamp - v_time) interval;
            -- se espera un intervalo positivo en el RAISE. 
        end loop;
    end;$$;
    

    Aquí, la diferencia se calcula entre el current_timestamp y el valor de marca de tiempo que se asigna a v_time después de que se haya ejecutado el comando pg_sleep. Además, el intervalo se formatea como un valor positivo utilizando la palabra clave “interval” en la declaración raise notice.

    Realizando estos cambios, deberías poder ver cuánto tiempo tarda cada iteración del bucle en completarse.

Comments are closed.