É recomendado declarar funções Oracle PL/SQL como PARALLEL_ENABLE
quando elas podem ser paralelizadas, para que o SGBD saiba que pode executar a função em paralelo.
Mas quando uma função é paralelizável? Ou melhor: quando não é?
Vejamos um exemplo:
CREATE OR REPLACE FUNCTION get_country_name(p_country_code VARCHAR2) RETURN VARCHAR2
PARALLEL_ENABLE
AS
PRAGMA UDF;
v_country_name country.name%TYPE;
BEGIN
SELECT name INTO v_country_name
FROM country
WHERE code = p_country_code;
RETURN v_country_name;
EXCEPTION WHEN OTHERS THEN
RETURN NULL;
END;
A função seleciona o nome do país para um determinado código de país, por exemplo, 'França' para 'FR'. Eu fiz UDF, porque vou usá-lo principalmente em consultas SQL, e tornei-o habilitado para paralelo, porque, bem, então funciona melhor em select /*+parallel(4)*/ get_country_name(code) from ...
- é isso que significa? Ou o que mais?
E por que posso declarar esta função PARALLEL_ENABLE
? O que exatamente o torna paralelizável? Posso simplesmente declarar todas as minhas funções PARALLEL_ENABLE
? Então eu deveria, não deveria? Ou existem circunstâncias que impediriam isso? O que impediria uma função de ser paralelizável?
PARALLEL_ENABLE
é um tanto misterioso. A documentação da Oracle não é muito clara. É certo que você não precisa disso na consulta paralela (PQ, paralelização deSELECT
blocos) - os escravos paralelos executarão alegremente suas funções escalares naSELECT
cláusula sem serem marcados comoPARALLEL_ENABLE
.Um lugar onde definitivamente faz diferença é com DML paralelo (pdml) ao usar funções não puras . De acordo com os documentos:
Na verdade, isso só é necessário quando a função não é pura e nem quando é PQ regular. Aqui está uma demonstração, usando arbitrariamente uma grande tabela que chamei de "instantâneo".
Isso executa a chamada de função em série e desativa efetivamente o funcionamento do pdml:
Plano de execução:
Como você pode ver, a
LOAD AS SELECT
operação vem acima/depoisPX COORDINATOR
, portanto não há PDML. A etapa de inserção real é serializada. Os comentários do plano até nos dão um exemplo do porquê. Claro que isso faz sentido: dependendo de qual escravo PX o executa, o resultado será diferente (já que estou retornando o SID do processo em execução). A Oracle não quer que obtenhamos resultados diferentes dependendo se o PX está envolvido ou não ou como as linhas são distribuídas, mas isso causaria isso.Então, temos que jurar em nossos túmulos que é isso que realmente queremos. Agora adicione
PARALLEL_ENABLE
:Plano de execução:
Agora
LOAD AS SELECT
vem abaixo/antesPX COORDINATOR
, então estamos em modo PDML completo aqui e essa inserção será muito mais rápida. A adiçãoPARALLEL_ENABLE
dessa função escalar tornou possível usá-la em uma operação PDML.Se a função fosse pure , a
PARALLEL_ENABLE
cláusula não seria necessária. O PDML funcionará perfeitamente sem ele, porque a Oracle sabe que o resultado não mudará, independentemente de como as linhas são distribuídas:Plano:
Ainda no modo PDML, mas sem
PARALLEL_ENABLE
.Existem outros usos para isso. Os documentos discutem isso em conexão com funções em pipeline, especialmente com cursores de referência, mas nunca vi isso funcionar definitivamente. Eu o adiciono rotineiramente às minhas funções de pipeline, mas minha execução sempre mostra saída serializada que é então distribuída para o primeiro conjunto de escravos PX. Nunca vi a saída em si paralelizada.
Talvez alguém possa colocar sua experiência aqui e tenha conseguido fazê-lo funcionar com funções de tabela em pipeline .
PARALLEL_ENABLE
costumava ser mais importante e era necessário para qualquer tipo de operação paralela. Os efeitos atuais são muito menores e são bem descritos pela resposta de Paulo.De acordo com a Referência da Linguagem PL/SQL do Banco de Dados 11.2 ,
PARALLEL_ENABLE
era necessário para permitir que a função fosse executada em paralelo:A Referência da Linguagem PL/SQL do Banco de Dados 12.2 agora explica que a cláusula se aplica principalmente a operações DML. Acho que a última frase da citação abaixo é um bug de documentação; o autor adicionou a primeira frase limitando o escopo desta cláusula, mas esqueceu de modificar a frase original que implicava que a cláusula se aplica a todas as operações paralelas.
Não tenho uma instância 11g para teste, mas acho que me lembro de ter que adicionar
PARALLEL_ENABLE
muitas funções, mesmo que não houvesse DML envolvido. E com base em meus testes, sua função usada em uma consulta deve ser executada com a mesma rapidez, com ou semPARALLEL_ENABLE
.