Documentation PostgreSQL 8.3.23 > Programmation serveur > Étendre SQL > Catégories de volatilité des fonctions | |
Surcharge des fonctions | Fonctions en langage de procédures |
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().
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'utilisattion d'instructions préparées ou avec l'utilisation de langages de fonctions mettant les plans d'exécutions en cache (comme PL/pgSQL).
À cause du comportement à base d'images de MVCC (voir le Chapitre 13, Contrôle d'accès simultané), 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 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. Notez aussi que la famille de fonctions current_timestamp est qualifiée de stable car leurs valeurs ne changent pas dans une transaction.
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.
Avant PostgreSQL™ version 8.0, le prérequis que les fonctions STABLE et IMMUTABLE ne pouvaient pas modifier la base de données n'était pas contraint par le système. La version 8.0 le contraint en réclamant que les fonctions SQL et les fonctions de langages de procédures de ces catégories ne contiennent pas de commandes SQL autre que SELECT (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).