PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 16.6 » Programmation serveur » Étendre SQL » Catégories de volatilité des fonctions

38.7. Catégories de volatilité des fonctions #

Chaque fonction a une classification de volatilité (volatility) comprenant VOLATILE, STABLE ou IMMUTABLE. VOLATILE est la valeur par défaut si la commande CREATE FUNCTION ne spécifie pas de catégorie. La catégorie de volatilité est une promesse à l'optimiseur sur le comportement de la fonction :

  • Une fonction VOLATILE peut tout faire, y compris modifier la base de données. Elle peut renvoyer différents résultats sur des appels successifs avec les mêmes arguments. L'optimiseur ne fait aucune supposition sur le comportement de telles fonctions. Une requête utilisant une fonction volatile ré-évaluera la fonction à chaque ligne où sa valeur est nécessaire.

  • Une fonction STABLE ne peut pas modifier la base de données et est garantie de renvoyer les mêmes résultats si elle est appelée avec les mêmes arguments pour toutes les lignes à l'intérieur d'une même instruction. Cette catégorie permet à l'optimiseur d'optimiser plusieurs appels de la fonction dans une seule requête. En particulier, vous pouvez utiliser en toute sécurité une expression contenant une telle fonction dans une condition de parcours d'index (car un parcours d'index évaluera la valeur de la comparaison une seule fois, pas une fois pour chaque ligne, utiliser une fonction VOLATILE dans une condition de parcours d'index n'est pas valide).

  • Une fonction IMMUTABLE ne peut pas modifier la base de données et est garantie de toujours renvoyer les mêmes résultats si elle est appelée avec les mêmes arguments. Cette catégorie permet à l'optimiseur de pré-évaluer la fonction quand une requête l'appelle avec des arguments constants. Par exemple, une requête comme SELECT ... WHERE x = 2 + 2 peut être simplifiée pour obtenir SELECT ... WHERE x = 4 car la fonction sous-jacente de l'opérateur d'addition est indiquée IMMUTABLE.

Pour une meilleure optimisation des résultats, vous devez mettre un label sur les fonctions avec la catégorie la plus volatile valide pour elles.

Toute fonction avec des effets de bord doit être indiquée comme VOLATILE, de façon à ce que les appels ne puissent pas être optimisés. Même une fonction sans effets de bord doit être indiquée comme VOLATILE si sa valeur peut changer à l'intérieur d'une seule requête ; quelques exemples sont random(), currval(), timeofday().

Un autre exemple important est que la famille de fonctions current_timestamp est qualifiée comme STABLE car leurs valeurs ne changent pas à l'intérieur d'une transaction.

Il y a relativement peu de différences entre les catégories STABLE et IMMUTABLE en considérant les requêtes interactives qui sont planifiées et immédiatement exécutées : il importe peu que la fonction soit exécutée une fois lors de la planification ou une fois au lancement de l'exécution de la requête mais cela fait une grosse différence si le plan est sauvegardé et utilisé plus tard. Placer un label IMMUTABLE sur une fonction quand elle ne l'est pas vraiment pourrait avoir comme conséquence de la considérer prématurément comme une constante lors de la planification et résulterait en une valeur erronée lors d'une utilisation ultérieure de ce plan d'exécution. C'est un danger qui arrive lors de l'utilisation d'instructions préparées ou avec l'utilisation de langages de fonctions mettant les plans d'exécutions en cache (comme PL/pgSQL).

Pour les fonctions écrites en SQL ou dans tout autre langage de procédure standard, la catégorie de volatibilité détermine une deuxième propriété importante, à savoir la visibilité de toute modification de données effectuées par la commande SQL qui a appelé la fonction. Une fonction VOLATILE verra les changements, une fonction STABLE ou IMMUTABLE ne les verra pas. Ce comportement est implantée en utilisant le comportement par images de MVCC (voir Chapitre 13) : les fonctions STABLE et IMMUTABLE utilisent une image établie au lancement de la requête appelante alors que les fonctions VOLATILE obtiennent une image fraiche au début de chaque requête qu'elles exécutent.

Note

Les fonctions écrites en C peuvent gérer les images de la façon qu'elles le souhaitent, mais il est préférable de coder les fonctions C de la même façon.

À cause du comportement à base d'images, une fonction contenant seulement des commandes SELECT peut être indiquée STABLE en toute sécurité même s'il sélectionne des données à partir de tables qui pourraient avoir subi des modifications entre temps par des requêtes concurrentes. PostgreSQL exécutera toutes les commandes d'une fonction STABLE en utilisant l'image établie par la requête appelante et n'aura qu'une vision figée de la base de données au cours de la requête.

Ce même comportement d'images est utilisé pour les commandes SELECT à l'intérieur de fonctions IMMUTABLE. Il est généralement déconseillé de sélectionner des tables de la base de données à l'intérieur de fonctions IMMUTABLE car l'immutabilité sera rompue si le contenu de la table change. Néanmoins, PostgreSQL ne vous force pas à ne pas le faire.

Une erreur commune est de placer un label sur une fonction IMMUTABLE quand son résultat dépend d'un paramètre de configuration. Par exemple, une fonction qui manipule des types date/heure pourrait bien avoir des résultats dépendant du paramètre TimeZone. Pour être sécurisées, de telles fonctions devraient avoir le label STABLE à la place.

Note

PostgreSQL requiert que les fonctions STABLE et IMMUTABLE ne contiennent aucune commande SQL autre que SELECT pour éviter les modifications de données (ceci n'a pas été complètement testé car de telles fonctions pourraient toujours appeler des fonctions VOLATILE qui modifient la base de données. Si vous le faites, vous trouverez que la fonction STABLE ou IMMUTABLE n'est pas au courant des modifications effectuées sur la base de données par la fonction appelée, car elles sont cachées depuis son image).