Pytanie dla początkujących:
Mam drogą funkcję f(x, y)
w dwóch kolumnach xiy w mojej tabeli bazy danych.
Chcę wykonać zapytanie, które daje mi wynik funkcji jako kolumny i nakłada na nią ograniczenie, coś w rodzaju
SELECT *, f(x, y) AS func FROM table_name WHERE func < 10;
Jednak to nie działa, więc będę musiał napisać coś takiego
SELECT *, f(x, y) AS func FROM table_name WHERE f(x, y) < 10;
Czy uruchomi to kosztowną funkcję dwukrotnie? Jak najlepiej to zrobić?
postgresql
postgresql-9.4
Jack black
źródło
źródło
STABLE
/IMMUTABLE
lubVOLATILE
?Odpowiedzi:
Utwórzmy funkcję, która ma efekt uboczny, abyśmy mogli zobaczyć, ile razy jest wykonywana:
A potem nazywaj to tak jak ty:
Jak widać, funkcja jest wywoływana co najmniej raz (z
WHERE
klauzuli), a gdy warunek jest spełniony, ponownie w celu wygenerowania wyniku.Aby uniknąć drugiego wykonania, możesz zrobić to, co sugeruje Edgar - mianowicie zawinąć zapytanie i odfiltrować zestaw wyników:
Aby dalej sprawdzić, jak to działa, można przejść do
pg_stat_user_functions
i sprawdzićcalls
tam (podanatrack_functions
jest ustawiona na „wszystkie”).Spróbujmy z czymś, co nie ma skutków ubocznych:
simple()
jest w rzeczywistości zbyt prosty, więc można go wstawiać , dlatego nie pojawia się w widoku. Niech to będzie nieuniknione:Wygląda to tak samo z efektami ubocznymi lub bez nich.
Zmiana
other_one()
doIMMUTABLE
zmiany zachowań (może zaskakująco) do gorszego, jak to będzie nazywane 13 razy w obu zapytaniami.źródło
Spróbuj nazwać to jeszcze raz:
źródło