PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie wirken sich die Schlüsselwörter IMMUTABLE, STABLE und VOLATILE auf das Verhalten der Funktion aus?

Das Schlüsselwort IMMUTABLE ist nie automatisch von pgAdmin oder Postgres hinzugefügt. Wer auch immer die Funktion erstellt oder ersetzt hat, hat das getan.

Die richtige Volatilität für die gegebene Funktion ist VOLATILE (auch die Standardeinstellung), nicht STABLE - oder es würde keinen Sinn machen, clock_timestamp() zu verwenden das ist VOLATILE im Gegensatz zu now() oder CURRENT_TIMESTAMP welche STABLE sind :Diese geben denselben Zeitstempel innerhalb derselben Transaktion zurück. Das Handbuch:

clock_timestamp() gibt die tatsächliche aktuelle Uhrzeit zurück, und daher ändert sich ihr Wert sogar innerhalb eines einzigen SQL-Befehls.

Das Handbuch warnt davor, dass die Volatilität STABLE funktioniert ...

ist für AFTER ungeeignet Trigger, die vom aktuellen Befehl geänderte Zeilen abfragen möchten.

.. weil eine wiederholte Auswertung der Triggerfunktion anders zurückgeben kann Ergebnisse für dieselbe Zeile. Also nicht STABLE .

Sie fragen:

Haben Sie eine Idee, warum die Funktion fünfmal korrekt zurückgegeben wurde, bevor sie den fünften Wert festhielt, wenn sie als IMMUTABLE festgelegt wurde? ?

Das Postgres-Wiki:

Mit 9.2 verwendet der Planer spezifische Pläne bezüglich der gesendeten Parameter (die Abfrage wird bei der Ausführung geplant), außer wenn die Abfrage mehrmals ausgeführt wird und der Planer entscheidet, dass der allgemeine Plan nicht zu viel teurer ist als die spezifischen Pläne.

Fette Hervorhebung von mir. Scheint bei IMMUTABLE keinen Sinn zu machen Funktion ohne Eingabeparameter. Aber das falsche Label wird durch VOLATILE überschrieben Funktion im Körper (voids function inlining ):ein anderer Abfrageplan kann dennoch sinnvoll sein.Verwandt:

  • Leistung gespeicherter PostgreSQL-Prozeduren

Beiseite

trunc() ist etwas schneller als floor() und tut dasselbe hier, da positive Zahlen garantiert sind:

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