PostgreSQL: inmutable, volátil, estable

11

No tengo claro el verdadero significado en las definiciones de funciones INMUTABLES, VOLÁTILES y ESTABLES.

Leí la documentación, específicamente las definiciones de cada uno.

INMUTABLE indica que la función no puede modificar la base de datos y siempre devuelve el mismo resultado cuando se le dan los mismos valores de argumento ; es decir, no realiza búsquedas en la base de datos ni utiliza información que no está directamente presente en su lista de argumentos. Si se da esta opción, cualquier llamada de la función con argumentos totalmente constantes puede reemplazarse inmediatamente con el valor de la función.

ESTABLE indica que la función no puede modificar la base de datos, y que dentro de un escaneo de una sola tabla devolverá de manera consistente el mismo resultado para los mismos valores de argumento , pero que su resultado podría cambiar en las declaraciones SQL. Esta es la selección apropiada para funciones cuyos resultados dependen de búsquedas en la base de datos, variables de parámetros (como la zona horaria actual), etc. (No es apropiado para los desencadenadores DESPUÉS que desean consultar filas modificadas por el comando actual). Tenga en cuenta también que La familia de funciones current_timestamp califica como estable, ya que sus valores no cambian dentro de una transacción.

VOLATILE indica que el valor de la función puede cambiar incluso dentro de un escaneo de una sola tabla, por lo que no se pueden realizar optimizaciones. Relativamente pocas funciones de la base de datos son volátiles en este sentido; Algunos ejemplos son random (), currval (), timeofday (). Pero tenga en cuenta que cualquier función que tenga efectos secundarios debe clasificarse como volátil, incluso si su resultado es bastante predecible, para evitar que las llamadas se optimicen. Un ejemplo es setval ().

Mi confusión viene con la condición de INMUTABLE y ESTABLE de que la función SIEMPRE o CONSISTENTE devuelve el mismo resultado dados los mismos argumentos.

La definición INMUTABLE establece que la función no busca en la base de datos ni utiliza información que no está directamente presente en su lista de argumentos. Entonces, para mí, eso significa que tales funciones se utilizan para manipular los datos proporcionados por el cliente, y no deberían tener sentencias SELECT ... aunque eso me parece un poco extraño.

Con STABLE, la definición es similar en el sentido de que dice que debería devolver constantemente el mismo resultado. Entonces, para mí, eso significa que cada vez que se llama a la función con los mismos argumentos, debería devolver los mismos resultados (las mismas filas exactas, cada vez).

Entonces, para mí ... eso significa que cualquier función que realice una SELECCIÓN en una tabla o tablas que se puedan actualizar, solo debería ser volátil.

Pero, de nuevo ... eso no me suena bien.

Llevando esto de vuelta a mi caso de uso, estoy escribiendo funciones que realizan sentencias SELECT con múltiples JOIN en tablas que se agregan constantemente, por lo que se espera que las llamadas a funciones devuelvan resultados diferentes cada vez que se llama, incluso con los mismos argumentos .

Entonces, ¿eso significa que mis funciones deberían ser VOLÁTILES? ¿Aunque la documentación indica que relativamente pocas funciones de la base de datos son volátiles en este sentido ?

¡Gracias!

Arroyos
fuente

Respuestas:

15

IMMUTABLEdebe ser una función pura, cuyos resultados dependen solo de sus entradas. Este es un requisito muy estricto; no pueden llamar a otras funciones no inmutables, no pueden acceder a las tablas, no pueden acceder al valor de las propiedades de configuración, etc.

STABLEpuede usar cualquier entrada que sea ellos mismos STABLE: otras STABLEo IMMUTABLEfunciones, y SELECTconsultas de tablas. Es seguro consultar tablas porque la vista de la función de esas tablas no cambiará dentro de la instantánea actual de la consulta. Puede acceder a los valores de GUC ( current_setting(...)) siempre que sepa que tampoco se asignarán dentro de la declaración actual.

VOLATILE Las funciones son todo lo que no se ajusta a lo anterior:

  • Cualquier cosa con efectos secundarios.
  • Todo lo que hace escribe
  • Cualquier cosa que consulte datos externos no administrados por la instantánea de PostgreSQL
  • ...

En general, simplemente deje todo a VOLATILEmenos que tenga una buena razón para no hacerlo.

La razón principal para usar IMMUTABLEes cuando se escriben funciones que se usarán como parte de expresiones de índice.

Craig Ringer
fuente
1
"No pueden acceder a las tablas". Para ser justos, pueden y lo hacen. Creo que una regla más general es que no se supone que las tablas muten significativamente sin reiniciar la base de datos.
Evan Carroll
Si STABLE permite el acceso a la tabla, ¿hay optimizaciones por encima / por encima de VOLATILE ...?
Brooks
No recuerdo fuera de mi cabeza, tendría que consultar documentos / código.
Craig Ringer
4

Para STABLE, la parte que debe poner en negrita es 'el resultado podría cambiar en las declaraciones SQL'

Se supone que las cosas INMUTABLES nunca cambiarán. Incluso si reinicia el servidor de base de datos, ejecución yum update(pero por supuesto no puede haber errores!), Cambiar la configuración (como datestyle, timezone, default_text_search_config, extra_float_digits, etc.), o reemplazar el hardware del servidor por completo (de la misma arquitectura que el hardware antiguo, por lo los archivos binarios siguen siendo compatibles).

Las funciones que describe suenan como ESTABLES, porque dentro de una sola instrucción SQL ejecutarán sus consultas utilizando la misma instantánea que tiene la consulta externa, por lo que cualquier cambio concurrente que haya realizado en esas otras tablas no sería visible. Ahora, si sus funciones abren una nueva conexión al servidor y ejecutan sus consultas dentro de esa conexión independiente, eso haría que la función sea volátil, ya que estarían usando diferentes instantáneas.

jjanes
fuente
Creo que entiendo los requisitos previos para INMUTABLE (nada puede cambiar ... nunca, entre consultas, conexiones, reinicios, destrucción y reconstrucción planetaria, INCLUSO SI se modifica la base de datos) y VOLATILE (la función salta fuera del contexto en que se llamaba) ¿Es eso correcto? Entonces, ¿parece ESTABLE simplemente significa que la función no modifica la base de datos y no accede a la base de datos fuera de su contexto? La definición de ESTABLE parece que es MUCHO más complicada de lo que realmente necesita ser ... ¿O estoy dejando algo afuera?
Brooks
PostgreSQL en realidad tiene algunos problemas IMMUTABLEy colaciones. Confía en que glibc(o, en la Pg más reciente, iconv) no cambiará las definiciones de intercalación. En realidad, lo hacen, y no proporcionan forma de detectar tales cambios. Puede conducir a la corrupción silenciosa del índice :(. Es principalmente un problema al replicar entre diferentes versiones del sistema operativo, etc.
Craig Ringer