PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment les mots clés IMMUTABLE, STABLE et VOLATILE affectent-ils le comportement de la fonction ?

Le mot clé IMMUTABLE n'est jamais ajouté automatiquement par pgAdmin ou Postgres. Celui qui a créé ou remplacé la fonction l'a fait.

La bonne volatilité pour la fonction donnée est VOLATILE (également la valeur par défaut), pas STABLE - ou cela n'aurait pas de sens d'utiliser clock_timestamp() qui est VOLATILE contrairement à now() ou CURRENT_TIMESTAMP qui sont STABLE :ceux-ci renvoient le même horodatage dans la même transaction. Le manuel :

clock_timestamp() renvoie l'heure actuelle réelle et, par conséquent, sa valeur change même au sein d'une seule commande SQL.

Le manuel avertit que la fonction volatilité STABLE ...

est inapproprié pour AFTER les déclencheurs qui souhaitent interroger les lignes modifiées par la commande en cours.

.. parce que l'évaluation répétée de la fonction de déclenchement peut renvoyer différent résultats pour la même ligne. Donc, pas STABLE .

Vous demandez :

Avez-vous une idée de la raison pour laquelle la fonction est retournée correctement cinq fois avant de s'en tenir à la cinquième valeur lorsqu'elle est définie sur IMMUTABLE ?

Le wiki Postgres :

Avec 9.2, le planificateur utilisera des plans spécifiques concernant les paramètres envoyés (la requête sera planifiée à l'exécution), sauf si la requête est exécutée plusieurs fois et le planificateur décide que le plan générique n'est pas trop cher que les plans spécifiques.

Bold emphase mienne. Ne semble pas avoir de sens pour un IMMUTABLE fonction sans paramètre d'entrée. Mais la fausse étiquette est remplacée par le VOLATILE fonction dans le corps (vides fonction inlining ) :un plan de requête différent peut toujours avoir du sens.Related :

  • Performances des procédures stockées PostgreSQL

À part

trunc() est légèrement plus rapide que floor() et fait de même ici, puisque les nombres positifs sont garantis :

SELECT (trunc(EXTRACT(EPOCH FROM clock_timestamp()) * 10) - 13885344000)::int