- UDFs executáveis iniciam um programa ou script externo (Python, Bash etc.) e enviam blocos de dados para ele via STDIN / STDOUT. Use-as para integrar código ou ferramentas existentes sem recompilar o ClickHouse. Elas têm maior sobrecarga por chamada em comparação com opções executadas no mesmo processo e são mais indicadas para lógicas mais pesadas ou quando é necessário um runtime diferente.
- UDFs SQL são definidas com
CREATE FUNCTIONexclusivamente em SQL. Elas são inline/expandidas no plano da consulta (sem separação de processo), o que as torna leves e ideais para reutilizar lógica de expressão ou simplificar colunas calculadas complexas. - UDFs WebAssembly experimentais executam código compilado em WebAssembly dentro de um sandbox no processo do servidor. Elas oferecem menor sobrecarga por chamada do que executáveis externos, com melhor isolamento do que extensões nativas, o que as torna adequadas para algoritmos personalizados escritos em linguagens que podem gerar WASM (por exemplo, C/C++/Rust).
- UDFs executáveis experimentais baseadas em driver permitem que um “driver” fornecido pelo operador transforme um trecho de código fornecido em
CREATE FUNCTION ... ENGINE = DriverName(...) AS '...'em uma UDF executável no momento da criação da função (por exemplo, por meio de compilação). Elas se baseiam em UDFs executáveis e exigem configuração do driver no lado do servidor.
Funções executáveis definidas pelo usuário
No ClickHouse Cloud, as UDFs executáveis estão em beta público e são criadas pela UI do console do Cloud. Consulte Funções definidas pelo usuário no Cloud para ver o fluxo de trabalho específico do Cloud.
user_defined_executable_functions_config.
A configuração de uma função contém as seguintes definições:
O comando deve ler os argumentos de
STDIN e enviar o resultado para STDOUT. O comando deve processar os argumentos iterativamente. Ou seja, após processar um fragmento de argumentos, ele deve aguardar o próximo fragmento.
Funções executáveis definidas pelo usuário
Exemplos
UDF de script embutido
test_function_sum manualmente, definindo execute_direct como 0, usando configuração XML ou YAML.
- XML
- YAML
Arquivo
test_function.xml (/etc/clickhouse-server/test_function.xml com as configurações de caminho padrão)./etc/clickhouse-server/test_function.xml
Query
Result
UDF a partir de script Python
STDIN e o retorna como uma string.
Crie test_function usando configuração em XML ou YAML.
- XML
- YAML
Arquivo
test_function.xml (/etc/clickhouse-server/test_function.xml com as configurações de caminho padrão)./etc/clickhouse-server/test_function.xml
Crie um arquivo de script
test_function.py na pasta user_scripts (/var/lib/clickhouse/user_scripts/test_function.py com as configurações de caminho padrão).
Query
Result
Leia dois valores de STDIN e retorne a soma deles como um objeto JSON
test_function_sum_json com argumentos nomeados e o formato JSONEachRow usando configuração XML ou YAML.
- XML
- YAML
Arquivo
test_function.xml (/etc/clickhouse-server/test_function.xml com o caminho padrão)./etc/clickhouse-server/test_function.xml
Crie o arquivo de script
test_function_sum_json.py na pasta user_scripts (/var/lib/clickhouse/user_scripts/test_function_sum_json.py com o caminho padrão).
Query
Result
Use parâmetros na configuração command
command (isso funciona apenas para funções definidas pelo usuário do tipo executable).
Isso também exige a opção execute_direct para evitar vulnerabilidades de expansão de argumentos do shell.
- XML
- YAML
Arquivo
test_function_parameter_python.xml (/etc/clickhouse-server/test_function_parameter_python.xml com as configurações de caminho padrão)./etc/clickhouse-server/test_function_parameter_python.xml
Crie o arquivo de script
test_function_parameter_python.py dentro da pasta user_scripts (/var/lib/clickhouse/user_scripts/test_function_parameter_python.py com as configurações de caminho padrão).
Query
Result
UDF com script de shell
- XML
- YAML
Arquivo
test_function_shell.xml (/etc/clickhouse-server/test_function_shell.xml com o caminho padrão)./etc/clickhouse-server/test_function_shell.xml
Crie o script
test_shell.sh dentro da pasta user_scripts (/var/lib/clickhouse/user_scripts/test_shell.sh com o caminho padrão).
/var/lib/clickhouse/user_scripts/test_shell.sh
Query
Result
Tratamento de erros
Avaliação de expressões de argumentos
&&, || e ?:.
No ClickHouse, os argumentos de funções (operadores) são sempre avaliados.
Isso acontece porque partes inteiras de colunas são avaliadas de uma só vez, em vez de cada linha ser calculada separadamente.
Execução de funções no processamento distribuído de consultas
SELECT f(sum(g(x))) FROM distributed_table GROUP BY h(y),
- se uma
distributed_tabletiver pelo menos dois shards, as funções ‘g’ e ‘h’ serão executadas em servidores remotos, e a função ‘f’ será executada no servidor solicitante. - se uma
distributed_tabletiver apenas um shard, todas as funções ‘f’, ‘g’ e ‘h’ serão executadas no servidor desse shard.
hostName, que retorna o nome do servidor em que está sendo executada para permitir o GROUP BY por servidores em uma consulta SELECT.
Se uma função em uma consulta for executada no servidor solicitante, mas você precisar executá-la em servidores remotos, poderá encapsulá-la em uma função agregada ‘any’ ou adicioná-la a uma chave no GROUP BY.
Funções definidas pelo usuário em SQL
Funções definidas pelo usuário em WebAssembly
Início rápido
Mais informações
Funções executáveis definidas pelo usuário baseadas em driver
Este é um recurso experimental que pode mudar de forma incompatível com versões anteriores em lançamentos futuros. Ative-o com a configuração de servidor
allow_experimental_executable_udf_drivers.ENGINE = DriverName(...), o ClickHouse executa o create_command do driver, passando a assinatura da função e o corpo do código; o driver compila ou processa esse corpo de outra forma e gera uma configuração de UDF executável, que o ClickHouse então armazena e carrega.
Isso permite que os administradores ofereçam aos usuários uma forma segura e restrita de definir funções em uma linguagem arbitrária (por exemplo, C compilado dentro de um contêiner em sandbox) sem dar a eles acesso aos arquivos de configuração ou ao sistema de arquivos do servidor. O conjunto de drivers disponíveis é controlado inteiramente pelo operador.
Habilitando drivers
-
Defina o controle experimental na configuração do servidor:
-
Aponte
user_defined_executable_function_drivers_configpara um ou mais arquivos de configuração de driver (com suporte a glob) e, opcionalmente, definadynamic_user_defined_executable_functions_path, o diretório em que as configurações geradas de UDFs executáveis são armazenadas:
SYSTEM RELOAD CONFIG, portanto os drivers podem ser adicionados, alterados ou removidos sem reiniciar o servidor.
Configuração do driver
<driver> no nível superior. Os campos a seguir são compatíveis:
Exemplo de configuração do driver:
Contrato de invocação do driver
CREATE FUNCTION é executado, create_command é invocado com as variáveis env configuradas e os seguintes argumentos:
--name <function_name>--return <return_type>(se uma cláusulaRETURNSestiver presente)--args <signature>(se uma cláusulaARGUMENTSestiver presente), em que a assinatura é a lista de argumentos declarados, por exemplox UInt8, y DateTime--<key> <value>para cada argumento de engine declarado fornecido emENGINE = DriverName(key = value)
AS) é enviado para a entrada padrão do comando. O comando deve imprimir a configuração de uma UDF executável em sua saída padrão. O formato é detectado automaticamente: uma saída que começa com < é tratada como XML; caso contrário, como YAML. O nome da função definido na configuração gerada deve corresponder ao nome que está sendo criado. Se create_command encerrar com um status diferente de zero, a instrução falhará com uma exceção que inclui o código de saída e o erro padrão do driver.
drop_command, quando presente, é invocado da mesma forma (sem um corpo de código no stdin) quando a função é removida.
Criando uma FUNCTION
create_command do driver, grava a configuração gerada em dynamic_user_defined_executable_functions_path e o carregador existente de UDF executáveis a carrega. A função pode então ser chamada como qualquer outra função.
Removendo uma função
DROP FUNCTION invoca o drop_command do driver (se houver), remove a configuração dinâmica gerada e o diretório de trabalho de cada função, recarrega o carregador de UDF executável e remove a consulta persistida.
Persistência e reinicialização
ATTACH FUNCTION ... no diretório de objetos SQL definidos pelo usuário, para que a função sobreviva à reinicialização do servidor. Na inicialização, as configurações geradas em dynamic_user_defined_executable_functions_path são carregadas diretamente, sem executar novamente o driver. Se uma instrução ATTACH FUNCTION persistida não tiver uma configuração gerada correspondente (por exemplo, se o diretório dinâmico tiver sido perdido), o driver será executado novamente para recriá-la.
Limitações
- A funcionalidade é experimental e fica condicionada a
allow_experimental_executable_udf_drivers. - Funções baseadas em driver não têm suporte com armazenamento replicado de funções definidas pelo usuário (
ON CLUSTERe<user_defined_zookeeper_path>), porque apenas a consulta que deu origem é replicada, não os artefatos gerados. - O
RESTOREde uma função baseada em driver a partir de backup preserva a consulta, mas não executa novamente o driver; a configuração gerada é materializada posteriormente pela recuperação na reinicialização.
Exemplo de drivers em C
programs/server/user_defined_executable_function_drivers_config.d/ que compilam e executam um corpo de função em C. Eles são exemplos e não são instalados pelos pacotes:
DockerC- compila e executa o código dentro de contêineres Docker em sandbox (--network=none --read-only --cap-drop=ALL --security-opt=no-new-privileges, além de limites de memória/CPU/PID), gerando uma UDFexecutable_pool.GVisorC- uma variante que executa o binário compilado no runtimerunscdo gVisor.UnsafeC- compila e executa o código diretamente no host, sem sandbox. Como o nome indica, não oferece isolamento e se destina apenas a ambientes confiáveis e testes.