As funções do Postgres são declaradas com classificação de volatilidade VOLATILE
, STABLE
ouIMMUTABLE
. O projeto é conhecido por ser muito rigoroso com esses rótulos para funções internas. E com razão. Exemplo proeminente: os índices de expressão permitem apenas IMMUTABLE
funções e essas devem ser verdadeiramente imutáveis para evitar resultados incorretos.
As funções definidas pelo usuário ainda podem ser declaradas conforme a escolha do proprietário. O manual aconselha:
Para obter melhores resultados de otimização, você deve rotular suas funções com a categoria de volatilidade mais estrita que seja válida para elas.
... e adiciona uma extensa lista de coisas que podem dar errado com um rótulo de volatilidade incorreto.
Ainda assim, há casos em que fingir imutabilidade faz sentido. Principalmente quando você sabe que a função é, de fato, imutável dentro do seu escopo. Exemplo:
Deixando de lado todas as possíveis implicações na integridade dos dados , qual é o efeito no desempenho? Pode-se supor que declarar uma função IMMUTABLE
só pode ser benéfico para o desempenho . É assim mesmo?
Declarar a volatilidade da função pode IMMUTABLE
prejudicar o desempenho?
Vamos assumir o Postgres 10 atual para reduzi-lo, mas todas as versões recentes são interessantes.
Sim, pode prejudicar o desempenho.
Funções SQL simples podem ser "embutidas" na consulta de chamada. Citando a Wiki do Postgres :
Minha ênfase em negrito .
Para impor a correção, há uma série de pré-condições. Um deles :
Ou seja, as funções SQL que usam quaisquer funções não imutáveis, mas que ainda estão sendo declaradas
IMMTUTABLE
, são excluídas dessa otimização. Acionado por essas respostas relacionadas no SO, tenho executado testes extensivos:Basicamente comparando essas duas variantes de uma função SQL simples (mapeamento de datas para um
integer
, ignorando o ano que não importa para o propósito):A função Postgres
to_char()
é apenasSTABLE
, nãoIMMUTABLE
(todas as instâncias sobrecarregadas dela - por motivos além do escopo desta resposta ). Então o segundo é falsoIMMUTABLE
e acaba sendo 5x mais lento em um teste simples:db<>fique aqui
Este exemplo específico pode ser substituído pelo equivalente:
Pareceria mais caro com duas chamadas de função e mais cálculos. Mas o
IMMUTABLE
rótulo é verdadeiro (além disso, a função usada é mais rápida e coagir étext
maisinteger
cara também).2x mais rápido que a variante mais rápida acima (10x mais rápido que a mais lenta). O ponto é: Use
IMMUTABLE
funções sempre que possível , então você não precisa "trapacear" para começar.