Las funciones de Postgres se declaran con clasificación de volatilidad VOLATILE
, STABLE
oIMMUTABLE
. Se sabe que el proyecto es muy estricto con estas etiquetas para las funciones integradas. Y con buen motivo. Ejemplo destacado: los índices de expresión solo permiten IMMUTABLE
funciones y esas deben ser verdaderamente inmutables para evitar resultados incorrectos.
Las funciones definidas por el usuario aún pueden declararse libremente según lo elija el propietario. El manual aconseja:
Para obtener los mejores resultados de optimización, debe etiquetar sus funciones con la categoría de volatilidad más estricta que sea válida para ellas.
... y agrega una extensa lista de cosas que pueden salir mal con una etiqueta de volatilidad incorrecta.
Aún así, hay casos en los que tiene sentido falsificar la inmutabilidad. Principalmente cuando sabe que la función es, de hecho, inmutable dentro de su alcance. Ejemplo:
Dejando a un lado todas las posibles implicaciones en la integridad de los datos , ¿cuál es el efecto en el rendimiento? Se podría suponer que declarar una función IMMUTABLE
solo puede ser beneficiosa para el rendimiento . ¿Es eso así?
¿La declaración de volatilidad de la función puede IMMUTABLE
dañar el rendimiento?
Supongamos que Postgres 10 actual lo reduce, pero todas las versiones recientes son de interés.
fuente
FORCE
cualquier manera. El 100% de los DBA PostgreSQL experimentados mienten para evitar esa interfaz de usuario con funciones de contenedor. Al menos conFORCE
, no necesitaríamos envoltorios y no tendríamos que mentir sobre la volatilidad declarada de fn.FORCE
se supone que los índices de expresión aceptan funciones no inmutables (al tiempo que los marcan como posibles puntos de falla). Sí, eso parecería una solución más elegante que los envoltorios de funciones inmutables.Respuestas:
Sí, puede dañar el rendimiento.
Las funciones SQL simples se pueden "en línea" en la consulta de llamada. Citando el Wiki de Postgres :
El énfasis audaz es mío.
Para hacer cumplir la corrección, hay una serie de condiciones previas. Uno de ellos :
Es decir, las funciones SQL que utilizan funciones no inmutables pero que aún se declaran
IMMTUTABLE
están excluidas de esta optimización. Activado por estas respuestas relacionadas en SO, he estado realizando pruebas exhaustivas:Básicamente, comparando estas dos variantes de una función SQL simple (asignando fechas a una
integer
, ignorando el año que no importa para ese propósito):La función Postgres
to_char()
es únicaSTABLE
, noIMMUTABLE
(todas las instancias sobrecargadas de la misma, por razones más allá del alcance de esta respuesta ). Entonces, el segundo es falsoIMMUTABLE
y resulta ser 5 veces más lento en una prueba simple:db <> violín aquí
Este ejemplo específico se puede reemplazar con el equivalente:
Sería parecer más caro con dos llamadas a funciones y más cálculos. Sin embargo, la
IMMUTABLE
etiqueta es verdadera (además, la función de uso es más rápido y coaccionartext
ainteger
es más caro, también).2 veces más rápido que la variante más rápida anterior (10 veces más rápido que el más lento). El punto es: usar
IMMUTABLE
funciones cuando sea posible , para no tener que "hacer trampa".fuente
STABLE
también está en línea. Pensé que el optimizador soloIMMUTABLE
funcionaría en línea .VOLATILE
igual de bien.