PostgreSQL: immuable, volatile, stable

11

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 lorsqu'elle reçoit les mêmes valeurs d'argument ; c'est-à-dire qu'il n'effectue pas de recherche 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 dans les instructions SQL. 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ètres (telles que le fuseau horaire actuel), etc. (Cela ne convient pas aux 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 avec la condition pour IMMUTABLE et STABLE que la fonction renvoie TOUJOURS ou CONSTAMMENT le même résultat étant donné 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 que relativement peu de fonctions de base de données sont volatiles dans ce sens ?

Je vous remercie!

Brooks
la source

Réponses:

15

IMMUTABLEdoit être une fonction pure, dont les résultats ne dépendent que 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.

STABLEpeut utiliser toutes les entrées qui sont elles-mêmes STABLE: autres STABLEou IMMUTABLEfonctions, et SELECTrequê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, VOLATILEsauf si vous avez une bonne raison de ne pas le faire.

La principale raison d'utiliser IMMUTABLEest lors de l'écriture de fonctions qui doivent être utilisées dans le cadre d'expressions d'index.

Craig Ringer
la source
1
"ils ne peuvent pas accéder aux tables." En toute justice, ils le peuvent et ils le font. Je pense qu'une règle plus générale est que les tables ne sont pas censées muter de manière significative sans redémarrage de la base de données.
Evan Carroll
Si STABLE autorise l'accès à la table, y a-t-il des optimisations au-dessus / au-dessus de VOLATILE ...?
Brooks
Je ne me souviens pas du haut de ma tête, devrait vérifier les documents / code.
Craig Ringer
4

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!), Changer votre configuration (comme datestyle, timezone, default_text_search_config, extra_float_digits, etc.), ou remplacer votre matériel de serveur entièrement (de la même architecture que l'ancien matériel, donc les fichiers binaires sont 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.

jjanes
la source
Je crois que je comprends les pré-requis pour IMMUTABLE (rien ne peut changer ... jamais, entre les requêtes, les connexions, les redémarrages, la destruction et la reconstruction planétaires, MÊME SI la base de données est modifiée) et VOLATILE (la fonction saute en dehors du contexte dans qui l’appelait). Est-ce exact? Alors, il apparaît que STABLE signifie simplement que la fonction ne modifie pas la base de données et n'accède pas à la base de données en dehors de son contexte? La définition de STABLE donne l'impression que c'est beaucoup plus compliqué qu'il ne faut vraiment ... Ou est-ce que je laisse de côté quelque chose?
Brooks
PostgreSQL a en fait des problèmes IMMUTABLEet des classements. Il espère que glibc(ou, dans la Pg plus récente, iconv) ne changera pas les définitions de classement. En réalité, ils le font et ne fournissent aucun moyen de détecter de tels changements. Cela peut conduire à une corruption d'index silencieuse :(. C'est principalement un problème lors de la réplication entre différentes versions de système d'exploitation, etc.
Craig Ringer