Anfängerfrage:
Ich habe eine teure Funktion f(x, y)
für zwei Spalten x und y in meiner Datenbanktabelle.
Ich möchte eine Abfrage ausführen, die mir das Ergebnis der Funktion als Spalte gibt und sie einschränkt, so etwas wie
SELECT *, f(x, y) AS func FROM table_name WHERE func < 10;
Dies funktioniert jedoch nicht, so dass ich so etwas schreiben muss
SELECT *, f(x, y) AS func FROM table_name WHERE f(x, y) < 10;
Wird dadurch die teure Funktion zweimal ausgeführt? Was ist der beste Weg, dies zu tun?
postgresql
postgresql-9.4
Jack Black
quelle
quelle
STABLE
/IMMUTABLE
oderVOLATILE
?Antworten:
Lassen Sie uns eine Funktion erstellen, die einen Nebeneffekt hat, damit wir sehen können, wie oft sie ausgeführt wird:
Und dann nenne das so wie du:
Wie Sie sehen, wird die Funktion mindestens einmal (aus der
WHERE
Klausel) aufgerufen , und wenn die Bedingung erfüllt ist, erneut, um die Ausgabe zu erzeugen.Um die zweite Ausführung zu vermeiden, können Sie das tun, was Edgar vorschlägt - nämlich die Abfrage umbrechen und die Ergebnismenge filtern:
Um weiter zu überprüfen, wie dies funktioniert, kann man dorthin gehen
pg_stat_user_functions
und nachsehencalls
(angegebentrack_functions
ist auf 'all' gesetzt).Versuchen wir es mit etwas, das keine Nebenwirkungen hat:
simple()
ist eigentlich zu einfach, so dass es inline sein kann , daher erscheint es nicht in der Ansicht. Machen wir es unsinnig:Wie es aussieht, ist das Bild mit oder ohne Nebenwirkungen dasselbe.
Durch Ändern
other_one()
inIMMUTABLE
wird das Verhalten (möglicherweise überraschend) verschlechtert, da es in beiden Abfragen 13 Mal aufgerufen wird.quelle
Versuchen Sie es erneut:
quelle