As funções do Postgres são declaradas com classificação de volatilidade VOLATILE
, STABLE
ouIMMUTABLE
. Sabe-se que o projeto é muito rigoroso com esses rótulos para funções internas. E por uma boa razão. Exemplo proeminente: os índices de expressão permitem apenas IMMUTABLE
funções e essas precisam ser realmente imutáveis para evitar resultados incorretos.
As funções definidas pelo usuário ainda estão livres para serem declaradas como o proprietário escolher. O manual aconselha:
Para obter melhores resultados de otimização, você deve rotular suas funções com a categoria de volatilidade mais estrita que é 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 é imutável dentro do seu escopo. Exemplo:
Além de 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?
A declaração da 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 de interesse.
fonte
FORCE
eles de qualquer maneira. 100% dos DBAs experientes do PostgreSQL mentem para contornar essa interface do usuário com funções de wrapper. Pelo menosFORCE
, não precisaríamos de invólucros e não precisaríamos mentir sobre a volatilidade declarada do fn.FORCE
é suposto fazer com que os índices de expressão aceitem funções não imutáveis (enquanto os marcam como possíveis pontos de falha). Sim, isso pareceria uma solução mais elegante do que invólucros imutáveis de funções.Respostas:
Sim, isso pode prejudicar o desempenho.
Funções SQL simples podem ser "incorporadas" na consulta de chamada. Citando o Wiki do Postgres :
Negrito ênfase minha.
Para impor a correção, existem várias pré-condições. Um deles :
Ou seja, funções SQL que usam funções não imutáveis, mas ainda sendo declaradas,
IMMTUTABLE
são excluídas dessa otimização. Acionado por essas respostas relacionadas ao SO, tenho executado extensos testes:Basicamente, comparando essas duas variantes de uma função SQL simples (mapear datas para um
integer
, ignorando o ano que não importa para o efeito):A função Postgres
to_char()
é apenasSTABLE
, nãoIMMUTABLE
(todas as instâncias sobrecarregadas dela - por razões fora do escopo desta resposta ). Portanto, o segundo é falsoIMMUTABLE
e acaba sendo 5x mais lento em um teste simples:db <> mexer aqui
Este exemplo específico pode ser substituído pelo equivalente:
Será que parecem mais caro com duas chamadas de função e mais cálculos. Mas o
IMMUTABLE
rótulo é verdadeira (mais, a função usada é mais rápido e coagirtext
ainteger
é mais caro, também).2x mais rápido que a variante mais rápida acima (10x mais rápido que o mais lento). A questão é: use
IMMUTABLE
funções sempre que possível , para não ter que "trapacear" para começar.fonte
STABLE
também é inline. Eu pensei que o otimizadorIMMUTABLE
funcionaria apenas online .VOLATILE
tão bem.