O planejador classifica as operações envolvidas em uma consulta como paralela segura, paralela restrita ou paralela insegura. Uma operação paralela segura é aquela que não entra em conflito com o uso de consulta paralelizada. Uma operação paralela restrita é aquela que não pode ser executada em um processo trabalhador paralelo, mas pode ser executada no líder enquanto a consulta paralelizada está em uso. Portanto, operações paralelas restritas nunca podem ocorrer abaixo de um nó Gather ou Gather Merge, mas podem ocorrer em outro lugar em um plano que contenha tal nó. Uma operação paralela insegura é aquela que não pode ser executada enquanto a consulta paralelizada está em uso, nem mesmo no líder. Quando uma consulta contém algo que não é seguro fazer em paralelo, a consulta paralelizada é completamente desativada para esta consulta.
As seguintes operações são sempre restritas ao paralelismo:
Varreduras de expressões de tabela comuns (CTEs).
Varreduras de tabelas temporárias.
Varreduras de tabelas externas, a menos que o empacotador de
dados externos tenha uma API
IsForeignScanParallelSafe indicando o contrário.
Nós de planejamento que fazem referência a um
SubPlan correlacionado.
O planejador não pode determinar automaticamente se uma função ou
agregação definida pelo usuário é paralela segura,
paralela restrita ou
paralela insegura, porque isto exigiria a
previsão de todas as operações que a função poderia executar.
Em geral, isto equivale ao
Problema da Parada, portanto, é impossível.
Mesmo para funções simples onde poderia ser feito, não é tentado,
porque seria caro e propenso a erros.
Em vez disso, todas as funções definidas pelo usuário são consideradas
paralelas inseguras, a menos que estejam marcadas de outra forma.
Quando é usado CREATE FUNCTION ou
ALTER FUNCTION, as marcações podem ser definidas
especificando PARALLEL SAFE,
PARALLEL RESTRICTED ou
PARALLEL UNSAFE, conforme seja apropriado.
Quando é usado CREATE AGGREGATE, a opção
PARALLEL pode ser especificada como
SAFE, RESTRICTED ou
UNSAFE, conforme seja apropriado.
Funções e agregações devem ser marcadas como
PARALLEL UNSAFE se escreverem no banco de dados,
alterarem o estado da transação (exceto usando uma subtransação
para recuperação de erros), acessarem sequências ou fizerem
alterações persistentes nas configurações.
De forma semelhante, as funções devem ser marcadas como
PARALLEL RESTRICTED se acessarem tabelas
temporárias, estado da conexão do cliente, cursores, instruções
preparadas ou qualquer estado de processo do servidor local que
o sistema não possa sincronizar entre diferentes processos
trabalhadores.
Por exemplo, setseed e random
têm paralelização restrita por este último motivo.
Em geral, se uma função é marcada como segura quando é restrita ou
insegura, ou se é marcada como restrita quando, na verdade, não é
segura, a função pode gerar erros, ou produzir respostas erradas,
quando usada em uma consulta paralelizada.
As funções da linguagem C podem, em teoria,
exibir um comportamento totalmente indefinido se marcadas
erroneamente, uma vez não haver como o sistema possa se proteger
contra um código C arbitrário, mas geralmente
o resultado não será pior que para qualquer outra função.
Em caso de dúvida, provavelmente é melhor rotular as funções como
UNSAFE.
Se uma função executada em um processo trabalhador paralelo adquirir
bloqueios que não são mantidos pelo líder, por exemplo, consultando
uma tabela não referenciada na consulta, estes bloqueios serão
liberados na saída do processo trabalhador, e não no final da transação.
Se for escrita uma função que faz isto, e esta diferença de
comportamento for importante, esta função deve ser marcada como
PARALLEL RESTRICTED para garantir que
seja executada apenas no líder.
Note que o planejador de consulta não considera adiar a avaliação
de funções ou agregações paralelas restritas envolvidas na consulta
para obter um plano superior.
Assim, por exemplo, se a cláusula WHERE aplicada
a uma determinada tabela for paralela restrita,
o planejador de consulta não vai considerar a realização de uma
varredura desta tabela na parte paralela do plano.
Em alguns casos, seria possível (e talvez até eficiente) incluir
a varredura desta tabela na parte paralela da consulta, e adiar a
avaliação da cláusula WHERE para ocorrer
acima do nó Gather.
Entretanto, o planejador não faz isto.