PostgreSQL: immutabile, volatile, stabile


11

Non sono chiaro il vero significato nelle definizioni delle funzioni IMMUTABILE, VOLATILE e STABILE.

Ho letto la documentazione, in particolare le definizioni di ciascuno.

IMMUTABLE indica che la funzione non può modificare il database e restituisce sempre lo stesso risultato quando vengono forniti gli stessi valori di argomento ; vale a dire, non effettua ricerche nel database né utilizza in altro modo informazioni non direttamente presenti nel suo elenco di argomenti. Se viene fornita questa opzione, qualsiasi chiamata della funzione con argomenti tutte costanti può essere immediatamente sostituita con il valore della funzione.

STABILE indica che la funzione non può modificare il database e che all'interno di una singola scansione della tabella restituirà costantemente lo stesso risultato per gli stessi valori dell'argomento , ma che il suo risultato potrebbe cambiare tra le istruzioni SQL. Questa è la selezione appropriata per le funzioni i cui risultati dipendono dalle ricerche nel database, dalle variabili dei parametri (come il fuso orario corrente), ecc. (È inappropriato per i trigger AFTER che desiderano interrogare le righe modificate dal comando corrente). Notare inoltre che il La famiglia di funzioni current_timestamp si qualifica come stabile, poiché i loro valori non cambiano all'interno di una transazione.

VOLATILE indica che il valore della funzione può cambiare anche all'interno di una singola scansione della tabella, quindi non è possibile effettuare ottimizzazioni. Relativamente poche funzioni di database sono volatili in questo senso; alcuni esempi sono random (), currval (), timeofday (). Si noti tuttavia che qualsiasi funzione che ha effetti collaterali deve essere classificata volatile, anche se il suo risultato è abbastanza prevedibile, per evitare che le chiamate vengano ottimizzate; un esempio è setval ().

La mia confusione si presenta con la condizione di IMMUTABILE e STABILE che la funzione SEMPRE o CONTINUAMENTE restituisca lo stesso risultato dati gli stessi argomenti.

La definizione IMMUTABLE afferma che la funzione non ricerca nel database o utilizza in altro modo informazioni non direttamente presenti nel suo elenco di argomenti. Quindi, per me, ciò significa che tali funzioni vengono utilizzate per manipolare i dati forniti dal client e non dovrebbero avere istruzioni SELECT ... anche se a me sembra un po 'strano.

Con STABLE, la definizione è simile in quanto afferma che dovrebbe costantemente restituire lo stesso risultato. Quindi, per me, ciò significa che ogni volta che la funzione viene chiamata con gli stessi argomenti, dovrebbe restituire gli stessi risultati (stesse righe esatte, ogni singola volta).

Quindi, per me ... ciò significa che qualsiasi funzione che esegue un SELECT su una o più tabelle che possono essere aggiornate, dovrebbe essere solo volatile.

Ma, di nuovo ... non mi sembra giusto.

Riportando questo nel mio caso d'uso, sto scrivendo funzioni che eseguono istruzioni SELECT con più JOIN su tabelle a cui vengono costantemente aggiunti, quindi ci si aspetta che le chiamate di funzione restituiscano risultati diversi ogni volta che viene chiamata, anche con gli stessi argomenti .

Quindi, ciò significa che le mie funzioni dovrebbero essere VOLATILI? Anche se la documentazione indica che relativamente poche funzioni del database sono volatili in questo senso ?

Grazie!

Risposte:


15

IMMUTABLEdeve essere una funzione pura, i cui risultati dipendono solo dai suoi input. Questo è un requisito molto rigoroso; non possono chiamare altre funzioni non immutabili, non possono accedere alle tabelle, non possono accedere al valore delle proprietà di configurazione, ecc.

STABLEpuò utilizzare qualsiasi input che sia esso stesso STABLE: altro STABLEo IMMUTABLEfunzioni e SELECTquery di tabelle. È sicuro interrogare le tabelle perché la visualizzazione della funzione di tali tabelle non cambierà nell'istantanea corrente della query. Puoi accedere ai valori GUC ( current_setting(...)) purché tu sappia che non saranno assegnati anche all'interno dell'istruzione corrente.

VOLATILE le funzioni sono tutto ciò che non corrisponde a quanto sopra:

  • Qualsiasi cosa con effetti collaterali
  • Tutto ciò che scrive
  • Tutto ciò che richiede dati esterni non gestiti dall'istantanea PostgreSQL
  • ...

In generale, lascia tutto, a VOLATILEmeno che tu non abbia una buona ragione per non farlo.

Il motivo principale da utilizzare IMMUTABLEè quando si scrivono funzioni da utilizzare come parte delle espressioni di indice.


1
"non possono accedere alle tabelle." In tutta onestà, possono e lo fanno. Penso che una regola più generale sia che le tabelle non dovrebbero mutare in modo significativo senza il riavvio del database.
Evan Carroll,

Se STABLE consente l'accesso alla tabella, ci sono ottimizzazioni sopra / sopra VOLATILE ...?
Brooks,

Non ricordo dalla parte superiore della mia testa, dovrei controllare documenti / codice.
Craig Ringer,

4

Per STABILE, la parte che devi mettere in grassetto è "il risultato potrebbe cambiare attraverso le istruzioni SQL"

Le cose IMMUTABILI non dovrebbero cambiare mai. Anche se si riavvia il server di database, run yum update(ma naturalmente non ci può essere insetti!), Modificare la configurazione (come datestyle, timezone, default_text_search_config, extra_float_digits, etc.), o sostituire l'hardware del server del tutto (della stessa architettura del vecchio hardware, quindi i file binari sono ancora compatibili).

Le funzioni che descrivi sembrano STABILI, perché all'interno di una singola istruzione SQL eseguiranno le loro query utilizzando la stessa istantanea della query esterna, e quindi eventuali modifiche simultanee apportate a quelle altre tabelle non sarebbero visibili. Ora, se le tue funzioni aprissero una nuova connessione al server ed eseguissero le loro query all'interno di quella connessione indipendente, ciò renderebbe la funzione volatile, poiché utilizzerebbero diverse istantanee.


Credo di comprendere i prerequisiti per IMMUTABLE (nulla può cambiare .... mai, tra query, connessioni, riavvii, distruzione planetaria e ricostruzione, ANCHE SE il database viene modificato) e VOLATILE (la funzione salta fuori dal contesto in che si chiamava). È corretto? Quindi, allora sembra STABILE significa semplicemente che la funzione non modifica il database e non accede al database al di fuori del suo contesto? La definizione di STABILE sembra MODO più complicata di quanto debba essere davvero ... O sto lasciando qualcosa fuori?
Brooks,

PostgreSQL ha effettivamente alcuni problemi IMMUTABLEe regole di confronto. Confida che glibc(o, nella più recente Pg, iconv) non cambierà le definizioni delle regole di confronto. In realtà, lo fanno e non forniscono alcun modo per rilevare tali cambiamenti. Può portare alla corruzione silenziosa dell'indice :(. È principalmente un problema durante la replica tra diverse versioni del sistema operativo, ecc.
Craig Ringer
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.