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.

¿Cómo encadeno una limpieza con VACUUM tras una rutina de purga en ejecución con pg_cron?

Postgres 13.4

Tengo algunos trabajos pg_cron configurados para eliminar periódicamente registros antiguos de archivos similares a registros. Lo que me gustaría hacer es ejecutar VACUUM ANALYZE después de realizar una purga. Desafortunadamente, no puedo averiguar cómo hacer esto en una función almacenada. ¿Estoy perdiendo algún truco? ¿Es un procedimiento almacenado más apropiado?

Como ejemplo, aquí hay una de mis rutinas de purga

CREATE OR REPLACE FUNCTION dba.purge<em>event</em>log (
    retain<em>days</em>in integer_positive default 14)

RETURNS int4

AS $BODY$

WITH  -- Use una CTE para que tengamos una forma de devolver fácilmente el recuento.
deleted AS (

-- El código normal para esto requiere un literal:
-- donde your_dts < now() - INTERVAL '14 days'
-- No quiero usar un literal, inyección SQL, etc.
-- En su lugar, utilizando un constructor de intervalos para lograr el mismo resultado:

DELETE
     FROM dba.event<em>log
    WHERE dts < now() - make</em>interval (days => $1)
RETURNING *
),

<hr>

<h2>-- Guarde los detalles en una tabla de registro personalizada</h2>

logit AS (
insert into dba.event<em>log (name, details)
    values ('purge</em>event<em>log(' || retain</em>days_in::text || ')',
             'count = ' || (select count(*)::text from deleted)
           )
)

<hr>

<h2>-- Devolver el recuento de resultados</h2>

select count(*) from deleted;

$BODY$
  LANGUAGE sql;

COMMENT ON FUNCTION dba.purge<em>event</em>log (integer<em>positive) IS
'Eliminar los registros de dba.event</em>log más antiguos que el número de días introducido, con un período de retención predeterminado de 14 días.';

<p>La verdad es que no me importa mucho el resultado de <code>count(*)</code> de esta rutina, <em>en este caso</em>. Pero podría querer un resultado y una acción adicional en algún otro contexto similar. Como puede ver, la rutina elimina registros, utiliza una CTE para <code>insertar</code> un informe en otra tabla y luego devuelve un resultado. Sea lo que sea, creo que este ejemplo es una buena manera de entender las alternativas y opciones en las funciones almacenadas. Lo principal que quiero lograr aquí es eliminar registros y luego ejecutar el mantenimiento. Si esto es incómodo para una función o un procedimiento almacenado, podría escribir una entrada en una tabla <code>vacuum_list</code> con el nombre de la tabla y tener otro trabajo que ejecute esa lista.</p>

<p>Si hay una forma más inteligente de abordar <code>vacuum</code> sin lo adicional, por supuesto que estoy interesado en eso. Pero también me interesa comprender las limitaciones de las operaciones que se pueden combinar en las rutinas PL/PgSQL.</p>

<p>La respuesta de Pavel Stehule es correcta y completa. Decidí seguir profundizando un poco más aquí, ya que me gusta investigar errores en mi código, comportamientos en Postgres, etc. para tener una mejor noción de lo que estoy tratando. A continuación, incluyo algunas notas para cualquier persona que las encuentre útiles.</p>

<h1>El COMANDO no se puede ejecutar…</h1>

<p>La referencia a "VACUUM no se puede ejecutar dentro de un bloque de transacción" me dio una mejor forma de buscar en la documentación comandos con restricciones similares. La información a continuación probablemente no cubre todo, pero es un comienzo.</p>

<p>“`
Comando Limitación
CREATE DATABASE
ALTER DATABASE Si se crea un nuevo espacio de tabla.
DROP DATABASE
CLUSTER Sin ningún parámetro.
CREATE TABLESPACE
DROP TABLESPACE
REINDEX Todo en los catálogos de sistema, la base de datos o el esquema.

CREATE SUBSCRIPTION Al crear una ranura de replicación (el comportamiento predeterminado).
ALTER SUBSCRIPTION Con la opción de actualización como verdadera.
DROP SUBSCRIPTION Si la suscripción está asociada con una ranura de replicación.

COMMIT PREPARED
ROLLBACK PREPARED
DISCARD ALL

VACUUM
“`

La respuesta aceptada indica que la limitación no tiene nada que ver con el lenguaje de servidor específico utilizado. Acabo de encontrar un hilo más antiguo que tiene algunas explicaciones y enlaces excelentes para funciones almacenadas y transacciones:

https://stackoverflow.com/questions/28250376/do-stored-procedures-run-in-database-transaction-in-postgres

Código de muestra

También me pregunté acerca de los procedimientos almacenados, ya que se les permite controlar transacciones. Los probé en PG 13 y no, el código se trata como una función almacen

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Usando VACUUM después de ejecutar trabajos pg_cron para eliminar registros

    Si desea limpiar las tablas de su base de datos ejecutando trabajos pg_cron para eliminar periódicamente registros antiguos, es posible que también desee ejecutar VACUUM ANALYZE después de cada purga para optimizar el rendimiento de la tabla. Sin embargo, no se puede ejecutar VACUUM desde una función o procedimiento almacenado en Postgres.

    Para abordar esta limitación, puede utilizar uno de varios enfoques alternativos, como utilizar un cliente externo o confiar en AUTOVACUUM y llamadas ocasionales de VACUUM. Otra opción es utilizar una tabla llamada vacuum_list para hacer un seguimiento de las tablas que necesitan ser vaciadas.

    Por ejemplo, puede insertar una fila en vacuum_list cuando una tabla necesita ser vaciada, especificando el nombre de la base de datos, el nombre del esquema y el nombre de la tabla, así como opciones para ejecutar VACUUM (por ejemplo, run, run_analyze y run_full). Luego, un cliente externo o un trabajo pg_cron pueden leer de esta tabla y ejecutar los comandos VACUUM correspondientes. También puede incluir campos en vacuum_list para la duración y el cambio de tamaño de la relación antes y después del vaciado.

    Si bien las funciones y procedimientos almacenados tienen limitaciones para ejecutar algunos comandos en Postgres (por ejemplo, CREATE DATABASE, DROP TABLESPACE, VACUUM, etc.), aún pueden ser útiles para definir consultas complejas para ejecutar en la base de datos. Si encuentra problemas al ejecutar comandos de Postgres desde funciones almacenadas, vale la pena consultar la documentación específica del comando o pedir consejo en foros como StackOverflow.

Comments are closed.