PostgreSQL: niezmienny, niestabilny, stabilny


11

Nie jestem pewien, jakie jest prawdziwe znaczenie definicji funkcji IMMUTABLE, VOLATILE i STABLE.

Czytam dokumentację, w szczególności definicje każdego z nich.

IMMUTABLE wskazuje, że funkcja nie może zmodyfikować bazy danych i zawsze zwraca ten sam wynik, jeśli podano te same wartości argumentów ; oznacza to, że nie wyszukuje w bazie danych ani nie wykorzystuje informacji, które nie są bezpośrednio obecne na liście argumentów. Jeśli podano tę opcję, każde wywołanie funkcji z całkowicie stałymi argumentami można natychmiast zastąpić wartością funkcji.

STABILNY wskazuje, że funkcja nie może modyfikować bazy danych i że podczas skanowania pojedynczej tabeli konsekwentnie zwróci ten sam wynik dla tych samych wartości argumentów , ale jej wynik może ulec zmianie w instrukcjach SQL. Jest to odpowiedni wybór dla funkcji, których wyniki zależą od wyszukiwania w bazie danych, zmiennych parametrów (takich jak bieżąca strefa czasowa) itp. (Jest nieodpowiedni dla wyzwalaczy AFTER, które chcą zapytać o wiersze zmodyfikowane przez bieżące polecenie.) Należy również pamiętać, że rodzina funkcji current_timestamp kwalifikuje się jako stabilna, ponieważ ich wartości nie zmieniają się w ramach transakcji.

VOLATILE wskazuje, że wartość funkcji może się zmienić nawet w ramach skanowania pojedynczej tabeli, więc nie można dokonać optymalizacji. W tym sensie stosunkowo niewiele funkcji bazy danych jest niestabilnych; niektóre przykłady to random (), currval (), timeofday (). Należy jednak pamiętać, że każda funkcja, która ma skutki uboczne, musi być klasyfikowana jako niestabilna, nawet jeśli jej wynik jest dość przewidywalny, aby zapobiec optymalizacji połączeń; przykładem jest setval ().

Moje zamieszanie przychodzi z warunkiem NIEZWYKŁEGO i STABILNEGO, że funkcja ZAWSZE lub ZGODNIE zwraca ten sam wynik, biorąc pod uwagę te same argumenty.

Definicja IMMUTABLE stwierdza, że ​​funkcja nie wyszukuje w bazie danych ani nie wykorzystuje informacji, które nie są bezpośrednio obecne na liście argumentów. Dla mnie oznacza to, że takie funkcje są używane do manipulowania danymi dostarczonymi przez klienta i nie powinny mieć instrukcji SELECT ... chociaż to wydaje mi się trochę dziwne.

W przypadku STABILNA definicja jest podobna, ponieważ mówi, że powinna konsekwentnie zwracać ten sam wynik. Dla mnie oznacza to, że za każdym razem, gdy funkcja jest wywoływana z tymi samymi argumentami, powinna zwracać te same wyniki (te same dokładne wiersze, za każdym razem).

Tak więc, dla mnie ... oznacza to, że każda funkcja, która wykonuje WYBÓR na stole lub tabelach, które mogą być aktualizowane, powinna być zmienna.

Ale znowu ... to nie brzmi dobrze.

Wracając do mojego przypadku użycia, piszę funkcje, które wykonują instrukcje SELECT z wieloma JOIN w tabelach, które są ciągle dodawane, więc wywołania funkcji powinny zwracać różne wyniki za każdym razem, gdy są wywoływane, nawet z tymi samymi argumentami .

Czy to oznacza, że ​​moje funkcje powinny być zmienne? Mimo że dokumentacja wskazuje, że stosunkowo niewiele funkcji bazy danych jest zmiennych w tym sensie ?

Dziękuję Ci!

Odpowiedzi:


15

IMMUTABLEmusi być funkcją czystą, której wyniki zależą tylko od jej danych wejściowych. Jest to bardzo surowy wymóg; nie mogą wywoływać innych niezmiennych funkcji, nie mają dostępu do tabel, nie mogą uzyskać dostępu do wartości właściwości konfiguracyjnych itp.

STABLEmoże używać dowolnych danych wejściowych, które same są STABLE: inne STABLElub IMMUTABLEfunkcje, oraz SELECTzapytań tabel. Można bezpiecznie wyszukiwać tabele, ponieważ widok funkcji tych tabel nie zmieni się w bieżącej migawce zapytania. Możesz uzyskać dostęp do wartości GUC ( current_setting(...)), o ile wiesz, że nie zostaną one również przypisane do bieżącej instrukcji.

VOLATILE funkcje to wszystko, co nie pasuje do powyższego:

  • Wszystko z efektami ubocznymi
  • Wszystko, co pisze
  • Wszystko, co wysyła zapytania do danych zewnętrznych, którymi nie zarządza migawka PostgreSQL
  • ...

Ogólnie rzecz biorąc, po prostu zostaw wszystko, VOLATILEchyba że masz dobry powód, aby tego nie robić.

Głównym powodem użycia IMMUTABLEjest pisanie funkcji, które mają być używane jako część wyrażeń indeksowych.


1
„nie mogą uzyskać dostępu do tabel”. Uczciwie mogą i robią. Myślę, że bardziej ogólną zasadą jest to, że tabele nie powinny znacząco mutować bez ponownego uruchomienia bazy danych.
Evan Carroll,

Jeśli STABILNY umożliwia dostęp do tabeli, czy istnieją jakieś optymalizacje powyżej / powyżej VOLATILE ...?
Brooks,

Nie pamiętam z góry głowy, musiałbym sprawdzić dokumenty / kod.
Craig Ringer

4

W przypadku STABILNEGO część, którą należy pogrubić, to „wynik może ulec zmianie w instrukcjach SQL”

NIEZWYKŁE rzeczy nie powinny się nigdy zmienić. Nawet jeśli po ponownym uruchomieniu serwera bazy danych, run yum update(ale oczywiście nie może być błędów!), Należy zmienić konfigurację (jak datestyle, timezone, default_text_search_config, extra_float_digits, itd), lub wymienić sprzęt serwera w całości (z tej samej architekturze co starego sprzętu, tak pliki binarne są nadal kompatybilne).

Funkcje, które opisujesz, brzmią tak, jakby były STABILNE, ponieważ w ramach jednej instrukcji SQL wykonają swoje zapytania przy użyciu tego samego obrazu stanu, co zewnętrzne zapytanie, a zatem wszelkie jednoczesne zmiany wprowadzone w tych innych tabelach nie będą widoczne. Teraz, jeśli twoje funkcje otworzą nowe połączenie z serwerem i uruchomią swoje zapytania w ramach tego niezależnego połączenia, to sprawi, że funkcja będzie niestabilna, ponieważ będą używać różnych migawek.


Wydaje mi się, że rozumiem warunki wstępne NIEZWYKŁE (nic nie może się zmienić ... nigdy, między zapytaniami, połączeniami, ponownym uruchomieniem, zniszczeniem i rekonstrukcją planet, NAWET JEŚLI baza danych zostanie zmodyfikowana) i WOLNE (funkcja wyskakuje poza kontekst w jak to się nazywało). Czy to jest poprawne? Więc, to wydaje się STABILNE, co oznacza, że ​​funkcja nie modyfikuje bazy danych i nie ma dostępu do bazy danych poza jej kontekstem? Definicja STABILNA wydaje się być DROGA bardziej skomplikowana niż musi być ... A może coś pomijam?
Brooks,

W PostgreSQL występują pewne problemy IMMUTABLEi sortowania. Ufa, że glibc(lub, w nowszych Pg, iconv) nie zmieni definicji sortowania. W rzeczywistości robią to i nie umożliwiają wykrycia takich zmian. Może to prowadzić do cichego uszkodzenia indeksu :(. Jest to głównie problem podczas replikacji między różnymi wersjami systemu operacyjnego itp.
Craig Ringer
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.