web-dev-qa-db-fra.com

PostgreSQL: immuable, volatile, stable

Je ne suis pas clair sur le vrai sens dans les définitions des fonctions IMMUTABLE, VOLATILE et STABLE.

J'ai lu la documentation, en particulier les définitions de chacun.

IMMUTABLE indique que la fonction ne peut pas modifier la base de données et renvoie toujours le même résultat quand on lui donne les mêmes valeurs d'argument; c'est-à-dire qu'il n'effectue pas de recherches dans la base de données ni n'utilise autrement les informations qui ne sont pas directement présentes dans sa liste d'arguments. Si cette option est donnée, tout appel de la fonction avec des arguments tous constants peut être immédiatement remplacé par la valeur de la fonction.

STABLE indique que la fonction ne peut pas modifier la base de données et que dans une seule analyse de table, elle retournera systématiquement le même résultat pour les mêmes valeurs d'argument, mais que son résultat pourrait changer d'une instruction SQL à l'autre. Il s'agit de la sélection appropriée pour les fonctions dont les résultats dépendent des recherches dans la base de données, des variables de paramètre (telles que le fuseau horaire actuel), etc. (Cela n'est pas approprié pour les déclencheurs AFTER qui souhaitent interroger des lignes modifiées par la commande actuelle.) Notez également que le La famille de fonctions current_timestamp est considérée comme stable, car leurs valeurs ne changent pas dans une transaction.

VOLATILE indique que la valeur de la fonction peut changer même au sein d'une seule analyse de table, donc aucune optimisation ne peut être effectuée. Relativement peu de fonctions de base de données sont volatiles dans ce sens; quelques exemples sont random (), currval (), timeofday (). Mais notez que toute fonction qui a des effets secondaires doit être classée comme volatile, même si son résultat est tout à fait prévisible, pour éviter que les appels ne soient optimisés; un exemple est setval ().

Ma confusion vient de la condition pour IMMUTABLE et STABLE que la fonction TOUJOURS ou SYSTÉMATIQUEMENT = renvoie le même résultat avec les mêmes arguments.

La définition IMMUTABLE indique que la fonction n'effectue pas de recherches dans la base de données ni n'utilise autrement les informations qui ne sont pas directement présentes dans sa liste d'arguments. Donc, pour moi, cela signifie que de telles fonctions sont utilisées pour manipuler les données fournies par le client, et ne devraient pas avoir d'instructions SELECT ... bien que cela me semble un peu étrange.

Avec STABLE, la définition est similaire en ce sens qu'elle indique qu'elle devrait toujours renvoyer le même résultat. Donc, pour moi, cela signifie que chaque fois que la fonction est appelée avec les mêmes arguments, elle devrait retourner les mêmes résultats (mêmes lignes exactes, à chaque fois).

Donc, pour moi ... cela signifie que toute fonction qui effectue un SELECT sur une table ou des tables qui peuvent être mises à jour, ne devrait être volatile.

Mais, encore une fois ... cela ne me semble pas juste.

Pour en revenir à mon cas d'utilisation, j'écris des fonctions qui exécutent des instructions SELECT avec plusieurs JOIN sur des tables qui sont constamment ajoutées, de sorte que les appels de fonction devraient renvoyer des résultats différents à chaque appel, même avec les mêmes arguments .

Alors, cela signifie-t-il que mes fonctions devraient être VOLATILES? Même si la documentation indique relativement peu de fonctions de base de données sont volatiles dans ce sens?

Je vous remercie!

11
Brooks

IMMUTABLE doit être une fonction pure, dont les résultats dépendent niquement de ses entrées. Il s'agit d'une exigence très stricte; ils ne peuvent pas appeler d'autres fonctions non immuables, ils ne peuvent pas accéder aux tables, ils ne peuvent pas accéder à la valeur des propriétés de configuration, etc.

STABLE peut utiliser toutes les entrées qui sont elles-mêmes STABLE: autres fonctions STABLE ou IMMUTABLE et SELECT requêtes de tables. Il est sûr d'interroger des tables car la vue de la fonction de ces tables ne changera pas dans l'instantané actuel de la requête. Vous pouvez accéder aux valeurs GUC (current_setting(...)) tant que vous savez qu'elles ne seront pas également affectées dans l'instruction en cours.

VOLATILE les fonctions sont tout ce qui ne correspond pas à ce qui précède:

  • Tout ce qui a des effets secondaires
  • Tout ce qui écrit
  • Tout ce qui interroge des données externes non gérées par l'instantané PostgreSQL
  • ...

En général, laissez tout VOLATILE sauf si vous avez une bonne raison de ne pas le faire.

La principale raison d'utiliser IMMUTABLE est lors de l'écriture de fonctions à utiliser dans le cadre d'expressions d'index.

15
Craig Ringer

Pour STABLE, la partie que vous devez mettre en gras est "le résultat peut changer dans les instructions SQL"

Les choses IMMUTABLES ne sont jamais censées changer. Même si vous redémarrez votre serveur de base de données, exécutez yum update (mais bien sûr il peut y avoir des bugs!), changez votre configuration (comme datestyle, timezone, default_text_search_config, extra_float_digits, etc.), ou remplacez entièrement le matériel de votre serveur (de la même architecture que l'ancien matériel, afin que les fichiers binaires soient toujours compatibles).

Les fonctions que vous décrivez semblent être STABLES, car dans une seule instruction SQL, elles exécuteront leurs requêtes en utilisant le même instantané que la requête externe, et donc toutes les modifications simultanées que vous avez apportées à ces autres tables ne seront pas visibles. Maintenant, si vos fonctions ouvraient une nouvelle connexion au serveur et exécutaient leurs requêtes dans cette connexion indépendante, cela rendrait la fonction volatile, car elles utiliseraient des instantanés différents.

4
jjanes