PostgreSQL: Imutável, Volátil, Estável

11

Não estou claro sobre o verdadeiro significado nas definições para funções IMMUTABLE, VOLATILE e STABLE.

Eu li a documentação, especificamente as definições de cada um.

IMMUTABLE indica que a função não pode modificar o banco de dados e sempre retorna o mesmo resultado quando recebe os mesmos valores de argumento ; isto é, não faz pesquisas de banco de dados ou usa informações que não estão diretamente presentes em sua lista de argumentos. Se essa opção for fornecida, qualquer chamada da função com argumentos sempre constantes poderá ser substituída imediatamente pelo valor da função.

STABLE indica que a função não pode modificar o banco de dados e, em uma única varredura de tabela, retornará consistentemente o mesmo resultado para os mesmos valores de argumento , mas que seu resultado poderá ser alterado nas instruções SQL. Essa é a seleção apropriada para funções cujos resultados dependem de pesquisas no banco de dados, variáveis ​​de parâmetro (como o fuso horário atual), etc. (É inadequado para gatilhos AFTER que desejem consultar linhas modificadas pelo comando atual.) A família de funções current_timestamp é qualificada como estável, pois seus valores não mudam dentro de uma transação.

VOLATILE indica que o valor da função pode mudar mesmo em uma única verificação de tabela, portanto, nenhuma otimização pode ser feita. Relativamente poucas funções de banco de dados são voláteis nesse sentido; alguns exemplos são random (), currval (), timeofday (). Mas observe que qualquer função que tenha efeitos colaterais deve ser classificada como volátil, mesmo que seu resultado seja bastante previsível, para impedir que as chamadas sejam otimizadas; um exemplo é setval ().

Minha confusão vem com a condição IMMUTABLE e STABLE de que a função SEMPRE ou CONSISTENTEMENTE retorne o mesmo resultado, com os mesmos argumentos.

A definição IMMUTABLE afirma que a função não pesquisa no banco de dados ou usa informações que não estão diretamente presentes em sua lista de argumentos. Então, para mim, isso significa que essas funções são usadas para manipular dados fornecidos pelo cliente e não devem ter instruções SELECT ... embora isso pareça um pouco estranho para mim.

Com STABLE, a definição é semelhante, pois diz que deve retornar consistentemente o mesmo resultado. Então, para mim, isso significa que toda vez que a função é chamada com os mesmos argumentos, ela deve retornar os mesmos resultados (mesmas linhas exatas, todas as vezes).

Então, para mim ... isso significa que qualquer função que executa um SELECT em uma tabela ou tabelas que podem ser atualizadas deve ser apenas volátil.

Mas, novamente ... isso não parece certo para mim.

Trazendo isso de volta ao meu caso de uso, estou escrevendo funções que executam instruções SELECT com várias JOIN em tabelas que são constantemente incluídas, portanto, espera-se que as chamadas de função retornem resultados diferentes sempre que forem chamadas, mesmo com os mesmos argumentos .

Então, isso significa que minhas funções devem ser VOLÁTEIS? Mesmo que a documentação indique que relativamente poucas funções do banco de dados são voláteis nesse sentido ?

Obrigado!

Brooks
fonte

Respostas:

15

IMMUTABLEdeve ser uma função pura, cujos resultados dependem apenas de suas entradas. Este é um requisito muito rigoroso; eles não podem chamar outras funções não imutáveis, não podem acessar tabelas, não podem acessar o valor das propriedades de configuração etc.

STABLEpode usar quaisquer entradas que sejam elas próprias STABLE: other STABLEou IMMUTABLEfunções e SELECTconsultas de tabelas. É seguro consultar tabelas porque a exibição da função dessas tabelas não será alterada no instantâneo atual da consulta. Você pode acessar os valores GUC ( current_setting(...)) desde que saiba que eles também não serão atribuídos na declaração atual.

VOLATILE funções são tudo o que não se encaixa no acima:

  • Qualquer coisa com efeitos colaterais
  • Qualquer coisa que escreva
  • Qualquer coisa que consulta dados externos não gerenciados pelo instantâneo do PostgreSQL
  • ...

Em geral, basta deixar tudo, a VOLATILEmenos que você tenha um bom motivo para não fazê-lo.

O principal motivo para usar IMMUTABLEé ao escrever funções que devem ser usadas como parte das expressões de índice.

Craig Ringer
fonte
11
"eles não podem acessar tabelas." Para ser justo, eles podem e o fazem. Eu acho que uma regra mais geral é que as tabelas não devem sofrer alterações significativas sem o reinício do banco de dados.
Evan Carroll
Se STABLE permitir o acesso à tabela, há otimizações acima / acima de VOLATILE ...?
Brooks
Não me lembro de cima da minha cabeça, teria que verificar documentos / código.
Craig Ringer
4

Para STABLE, a parte que você precisa colocar em negrito é 'o resultado pode mudar nas instruções SQL'

Coisas imutáveis ​​não devem mudar nunca. Mesmo se você reiniciar o servidor de banco de dados, run yum update(mas é claro que não pode haver erros!), Alterar a configuração (como datestyle, timezone, default_text_search_config, extra_float_digits, etc.), ou substituir o hardware do servidor totalmente (da mesma arquitetura como o hardware antigo, portanto, os arquivos binários ainda são compatíveis).

As funções que você descreve parecem estar STABLE, porque em uma única instrução SQL elas executam suas consultas usando o mesmo instantâneo da consulta externa e, portanto, quaisquer alterações simultâneas feitas nessas outras tabelas não seriam visíveis. Agora, se suas funções abrissem uma nova conexão com o servidor e executassem suas consultas nessa conexão independente, isso tornaria a função volátil, porque eles usariam instantâneos diferentes.

jjanes
fonte
Eu acredito que entendo os pré-requisitos para IMMUTABLE (nada pode mudar .... sempre, entre consultas, conexões, reinicializações, destruição e reconstrução planetária, mesmo que o banco de dados seja modificado) e VOLATILE (a função salta para fora do contexto em que foi chamado). Isso está correto? Então, parece STABLE simplesmente significa que a função não modifica o banco de dados e não acessa o banco de dados fora do seu contexto? A definição de STABLE parece muito mais complicada do que realmente precisa ser ... Ou estou deixando algo de fora?
Brooks
O PostgreSQL realmente tem alguns problemas IMMUTABLEe agrupamentos. Confia que glibc(ou, na página mais recente, iconv) não alterará as definições de agrupamento. Na realidade, eles fazem, e não fornecem nenhuma maneira de detectar tais mudanças. Ela pode levar à corrupção do índice silenciosa :( É principalmente uma questão ao replicar entre diferentes versões do sistema operacional, etc..
Craig Ringer