¿Hay alguna forma de establecer un tiempo de "caducidad", después del cual una entrada de datos se elimina automáticamente en PostgreSQL?

107

¿Hay alguna forma de establecer algún tipo de tiempo de "caducidad" en las entradas de datos en PostgreSQL ? Estoy pensando en algo equivalente a EXPIREen Redis .

No estoy buscando almacenar una marca de tiempo y luego codificar manualmente algún tipo de trabajo cron para verificar qué entradas han expirado.

Estoy tratando de averiguar si hay alguna característica nativa en PostgreSQL que proporcione este tipo de funcionalidad, o si tendría sentido solicitar dicha característica para futuras versiones.

Pensierinmusica
fuente
1
Hubo una discusión en la lista de correo de postgresql postgresql.org/message-id/…
vonPetrushev

Respuestas:

105

No hay una función de caducidad incorporada, pero si su objetivo es caducar automáticamente los campos y tener la lógica contenida dentro de su base de datos (y, por lo tanto, no hay dependencia externa como un trabajo cron), entonces siempre puede escribir un disparador. A continuación, se muestra un ejemplo de un desencadenador que elimina filas de una tabla que tienen una marca de tiempo anterior a 1 minuto. Se ejecuta cada vez que se inserta una nueva fila en esa misma tabla. Obviamente, puede configurar el disparador para que se ejecute en otras condiciones y para varias fechas de vencimiento según sea necesario. Utilicé el siguiente sitio web como base para esto: http://www.the-art-of-web.com/sql/trigger-delete-old/

CREATE TABLE expire_table (
    timestamp timestamp NOT NULL DEFAULT NOW(),
    name TEXT NOT NULL
);

INSERT INTO expire_table (name) VALUES ('a');
INSERT INTO expire_table (name) VALUES ('b');
INSERT INTO expire_table (name) VALUES ('c');

select * from expire_table;
         timestamp          | name 
----------------------------+------
 2014-09-26 15:33:43.243356 | a
 2014-09-26 15:33:45.222202 | b
 2014-09-26 15:33:47.347131 | c
(3 rows)

CREATE FUNCTION expire_table_delete_old_rows() RETURNS trigger
    LANGUAGE plpgsql
    AS $$
BEGIN
  DELETE FROM expire_table WHERE timestamp < NOW() - INTERVAL '1 minute';
  RETURN NEW;
END;
$$;

CREATE TRIGGER expire_table_delete_old_rows_trigger
    AFTER INSERT ON expire_table
    EXECUTE PROCEDURE expire_table_delete_old_rows();

INSERT INTO expire_table (name) VALUES ('d');

select * from expire_table;
         timestamp          | name 
----------------------------+------
 2014-09-26 15:36:56.132596 | d
(1 row)
Brett DiDonato
fuente
1
@caeus probablemente depende del almacenamiento en caché y la indexación
Nimrod
39
-1. En mi humilde opinión, los desencadenantes no son la forma en que debe lidiar con las funciones faltantes de la base de datos, porque los desencadenantes son difíciles de probar, difíciles de mantener y solo un dolor en el trasero. Sea honesto e impleméntelo en su aplicación. :)
Bastian Voigt
2
De acuerdo, creo que verificar los registros antiguos y eliminarlos en cada inserción es una solución realmente terrible en términos de rendimiento. No es tan difícil configurar incluso algo como el script de trabajo CRON que se ejecuta requiere SQL, por ejemplo.
zarkone
el rendimiento debería ser bastante bueno si hay un índice sobre el tiempo de vencimiento.
Jasen
2
+1 a la solución de Brett. Para algo como una tabla de sesión en la que solo desearía que un usuario tuviera una sola sesión, creo que un activador en cualquier INSERT en la tabla de sesión, para asegurarse de que cada usuario solo tenga una sesión, es un caso de uso perfectamente válido . Las personas se obsesionan con si algo es "comprobable", por lo que escriben soluciones más complejas (que luego necesitan pruebas intensas) en lugar de una función simple que pueden estar seguros de que no se romperá.
corysimmons
8

No. No existe tal característica.

No puedo ver lo que hace más que (1) solo una marca de tiempo "expirada" o (2) marca de tiempo + cron-job / pgAgent.

No suena como una característica general que se agregaría al núcleo. Podría simplemente codificar una extensión para manejar este tipo de cosas, ya sea con un tick llamado desde un cron-job o tal vez un proceso de background-worker .

No veo nada en pgxn , por lo que presumiblemente aún no ha habido mucha demanda.

Richard Huxton
fuente
3
Sé que esta respuesta es antigua, pero en mi opinión es una característica increíblemente útil, por ejemplo: docs.mongodb.com/manual/core/index-ttl
Madbreaks
requeriría mucho trabajo agregar esta característica a postgresql, por ejemplo, la creación de claves externas necesitaría reglas diferentes ...
Jasen