Existe-t-il un moyen de définir un délai «d'expiration», après lequel une entrée de données est automatiquement supprimée dans PostgreSQL?

108

Existe-t-il un moyen de définir une sorte de délai "d'expiration" sur les entrées de données dans PostgreSQL ? Je pense à quelque chose d'équivalent EXPIREdans Redis .

Je ne cherche pas à stocker un horodatage, puis à coder manuellement une sorte de travail cron pour vérifier quelles entrées ont expiré.

J'essaie de savoir s'il existe une fonctionnalité native dans PostgreSQL qui fournirait ce type de fonctionnalité, ou s'il serait logique de demander une telle fonctionnalité pour les versions futures.

Pensierinmusica
la source
1
Il y a eu une discussion sur la liste de diffusion postgresql postgresql.org/message-id
...

Réponses:

106

Il n'y a pas de fonction d'expiration intégrée, mais si votre objectif est d'expirer automatiquement les champs et d'avoir la logique contenue dans votre base de données (et donc pas de dépendance extérieure comme une tâche cron), vous pouvez toujours écrire un déclencheur. Vous trouverez ci-dessous un exemple de déclencheur qui supprime les lignes d'une table dont l'horodatage est supérieur à 1 minute. Il est exécuté chaque fois qu'une nouvelle ligne est insérée dans cette même table. Vous pouvez évidemment définir le déclencheur pour qu'il s'exécute à d'autres conditions et pour différentes dates d'expiration selon les besoins. J'ai utilisé le site Web suivant comme base pour cela: 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
la source
1
@caeus dépend probablement de la mise en cache et de l'indexation
Nimrod
39
-1. À mon avis, les déclencheurs ne sont pas la façon dont vous devriez gérer les fonctionnalités de base de données manquantes, car les déclencheurs sont difficiles à tester, difficiles à maintenir et juste une douleur dans le cul. Soyez honnête et implémentez-le dans votre application. :)
Bastian Voigt
2
D'accord, je pense que vérifier les anciens enregistrements et les supprimer sur chaque insert est une solution vraiment terrible en termes de performances. Ce n'est pas si difficile de configurer même quelque chose comme le script de travail CRON qui s'exécute nécessite SQL, par exemple.
zarkone
perfprmance devrait être assez bonne s'il y a un index sur le délai d'expiration.
Jasen le
2
+1 à la solution de Brett. Pour quelque chose comme une table de session où vous ne voudriez jamais qu'un utilisateur ait une seule session, je pense qu'un déclencheur sur n'importe quel INSERT dans la table de session, pour s'assurer que chaque utilisateur n'a qu'une seule session, est un cas d'utilisation parfaitement valide . Les gens sont obsédés par le fait de savoir si quelque chose est "testable", donc ils écrivent des solutions plus complexes (qui nécessitent alors des tests intensifs) plutôt qu'une fonction simple dont ils peuvent être sûrs qu'elle ne cassera pas.
corysimmons
8

Non, une telle fonctionnalité n'existe pas.

Je ne peux pas voir ce qu'il fait plus que (1) juste un horodatage "expiré" ou (2) horodatage + cron-job / pgAgent.

Cela ne ressemble pas à une fonctionnalité générale qui serait ajoutée au noyau. Vous pouvez tout simplement coder une extension pour gérer ce genre de choses, avec une coche appelée à partir d'un travail cron ou peut-être un processus de travail en arrière-plan .

Je ne vois rien sur pgxn , donc il n'y a probablement pas encore beaucoup de demande pour cela.

Richard Huxton
la source
3
Je sais que cette réponse est ancienne mais IMO c'est une fonctionnalité incroyablement utile, par exemple: docs.mongodb.com/manual/core/index-ttl
Madbreaks
cela demanderait beaucoup de travail pour ajouter cette fonctionnalité à postgresql, par exemple, la création de clé étrangère nécessiterait des règles différentes ...
Jasen