Pular para o conteúdo principal
O ClickHouse oferece suporte a vários tipos de funções definidas pelo usuário (UDFs):
  • 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 FUNCTION exclusivamente 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).

Funções executáveis definidas pelo usuário

Este recurso está disponível em visualização privada no ClickHouse Cloud. Entre em contato com o suporte do ClickHouse em https://clickhouse.cloud/support para obter acesso.
O ClickHouse pode chamar qualquer programa executável externo ou script para processar dados. A configuração das funções executáveis definidas pelo usuário pode estar em um ou mais arquivos XML. O caminho para a configuração é especificado no parâmetro user_defined_executable_functions_config. A configuração de uma função contém as seguintes definições:
ParâmetroDescriçãoObrigatórioValor padrão
nameNome da funçãoSim-
commandNome do script a ser executado ou comando, se execute_direct for falseSim-
argumentDescrição do argumento com o type e, opcionalmente, o name de um argumento. Cada argumento é descrito em uma configuração separada. Especificar o nome é necessário se os nomes dos argumentos fizerem parte da serialização do formato da função definida pelo usuário, como Native ou JSONEachRowSimc + argument_number
formatUm formato no qual os argumentos são passados para o comando. Também se espera que a saída do comando use o mesmo formatoSim-
return_typeO tipo de um valor retornadoSim-
return_nameNome do valor retornado. Especificar o nome de retorno é necessário se ele fizer parte da serialização do formato da função definida pelo usuário, como Native ou JSONEachRowOpcionalresult
typeUm tipo de executável. Se type estiver definido como executable, um único comando será iniciado. Se estiver definido como executable_pool, um pool de comandos será criadoSim-
max_command_execution_timeTempo máximo de execução, em segundos, para processar um bloco de dados. Essa configuração é válida apenas para comandos executable_poolOpcional10
command_termination_timeoutTempo, em segundos, durante o qual um comando deve ser encerrado após o fechamento de seu pipe. Após esse período, SIGTERM é enviado ao processo que executa o comandoOpcional10
command_read_timeoutTimeout para ler dados do stdout do comando, em milissegundosOpcional10000
command_write_timeoutTimeout para gravar dados no stdin do comando, em milissegundosOpcional10000
pool_sizeO tamanho de um pool de comandosOpcional16
send_chunk_headerControla se a contagem de linhas deve ser enviada antes de enviar um fragmento de dados para o processoOpcionalfalse
execute_directSe execute_direct = 1, então command será procurado dentro da pasta user_scripts especificada por user_scripts_path. Argumentos adicionais do script podem ser especificados usando espaço em branco como separador. Exemplo: script_name arg1 arg2. Se execute_direct = 0, command é passado como argumento para bin/sh -cOpcional1
lifetimeO intervalo de recarga de uma função, em segundos. Se estiver definido como 0, a função não será recarregadaOpcional0
deterministicIndica se a função é determinística (retorna o mesmo resultado para a mesma entrada)Opcionalfalse
stderr_reactionComo lidar com a saída de stderr do comando. Valores: none (ignorar), log (registrar todo o stderr imediatamente), log_first (registrar os primeiros 4 KiB após a saída), log_last (registrar os últimos 4 KiB após a saída), throw (lançar uma exceção imediatamente em caso de qualquer saída no stderr). Ao usar log_first ou log_last com um código de saída diferente de zero, o conteúdo de stderr é incluído na mensagem da exceçãoOpcionallog_last
check_exit_codeSe true, o ClickHouse verificará o código de saída do comando. Um código de saída diferente de zero causa uma exceçãoOpcionaltrue
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

Crie test_function_sum manualmente, definindo execute_direct como 0, usando configuração XML ou 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
<functions>
    <function>
        <type>executable</type>
        <name>test_function_sum</name>
        <return_type>UInt64</return_type>
        <argument>
            <type>UInt64</type>
            <name>lhs</name>
        </argument>
        <argument>
            <type>UInt64</type>
            <name>rhs</name>
        </argument>
        <format>TabSeparated</format>
        <command>cd /; clickhouse-local --input-format TabSeparated --output-format TabSeparated --structure 'x UInt64, y UInt64' --query "SELECT x + y FROM table"</command>
        <execute_direct>0</execute_direct>
        <deterministic>true</deterministic>
    </function>
</functions>

Query
SELECT test_function_sum(2, 2);
Result
┌─test_function_sum(2, 2)─┐
│                       4 │
└─────────────────────────┘

UDF a partir de script Python

Neste exemplo, criamos uma UDF que lê um valor de STDIN e o retorna como uma string. Crie test_function usando configuração em XML ou 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
<functions>
    <function>
        <type>executable</type>
        <name>test_function_python</name>
        <return_type>String</return_type>
        <argument>
            <type>UInt64</type>
            <name>value</name>
        </argument>
        <format>TabSeparated</format>
        <command>test_function.py</command>
    </function>
</functions>

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).
#!/usr/bin/python3

import sys

if __name__ == '__main__':
    for line in sys.stdin:
        print("Value " + line, end='')
        sys.stdout.flush()
Query
SELECT test_function_python(toUInt64(2));
Result
┌─test_function_python(2)─┐
│ Value 2                 │
└─────────────────────────┘

Leia dois valores de STDIN e retorne a soma deles como um objeto JSON

Crie test_function_sum_json com argumentos nomeados e o formato JSONEachRow usando configuração XML ou YAML.
Arquivo test_function.xml (/etc/clickhouse-server/test_function.xml com o caminho padrão).
/etc/clickhouse-server/test_function.xml
<functions>
    <function>
        <type>executable</type>
        <name>test_function_sum_json</name>
        <return_type>UInt64</return_type>
        <return_name>result_name</return_name>
        <argument>
            <type>UInt64</type>
            <name>argument_1</name>
        </argument>
        <argument>
            <type>UInt64</type>
            <name>argument_2</name>
        </argument>
        <format>JSONEachRow</format>
        <command>test_function_sum_json.py</command>
    </function>
</functions>

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).
#!/usr/bin/python3

import sys
import json

if __name__ == '__main__':
    for line in sys.stdin:
        value = json.loads(line)
        first_arg = int(value['argument_1'])
        second_arg = int(value['argument_2'])
        result = {'result_name': first_arg + second_arg}
        print(json.dumps(result), end='\n')
        sys.stdout.flush()
Query
SELECT test_function_sum_json(2, 2);
Result
┌─test_function_sum_json(2, 2)─┐
│                            4 │
└──────────────────────────────┘

Use parâmetros na configuração command

Funções executáveis definidas pelo usuário podem receber parâmetros constantes configurados na configuração 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.
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
<functions>
    <function>
        <type>executable</type>
        <execute_direct>true</execute_direct>
        <name>test_function_parameter_python</name>
        <return_type>String</return_type>
        <argument>
            <type>UInt64</type>
        </argument>
        <format>TabSeparated</format>
        <command>test_function_parameter_python.py {test_parameter:UInt64}</command>
    </function>
</functions>

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).
#!/usr/bin/python3

import sys

if __name__ == "__main__":
    for line in sys.stdin:
        print("Parameter " + str(sys.argv[1]) + " value " + str(line), end="")
        sys.stdout.flush()
Query
SELECT test_function_parameter_python(1)(2);
Result
┌─test_function_parameter_python(1)(2)─┐
│ Parameter 1 value 2                  │
└──────────────────────────────────────┘

UDF com script de shell

Neste exemplo, criamos um script de shell que multiplica cada valor por 2.
Arquivo test_function_shell.xml (/etc/clickhouse-server/test_function_shell.xml com o caminho padrão).
/etc/clickhouse-server/test_function_shell.xml
<functions>
    <function>
        <type>executable</type>
        <name>test_shell</name>
        <return_type>String</return_type>
        <argument>
            <type>UInt8</type>
            <name>value</name>
        </argument>
        <format>TabSeparated</format>
        <command>test_shell.sh</command>
    </function>
</functions>

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
#!/bin/bash

while read read_data;
    do printf "$(expr $read_data \* 2)\n";
done
Query
SELECT test_shell(number) FROM numbers(10);
Result
    ┌─test_shell(number)─┐
 1. │ 0                  │
 2. │ 2                  │
 3. │ 4                  │
 4. │ 6                  │
 5. │ 8                  │
 6. │ 10                 │
 7. │ 12                 │
 8. │ 14                 │
 9. │ 16                 │
10. │ 18                 │
    └────────────────────┘

Tratamento de erros

Algumas funções podem gerar uma exceção se os dados forem inválidos. Nesse caso, a consulta é cancelada e uma mensagem de erro é retornada ao cliente. No processamento distribuído, quando ocorre uma exceção em um dos servidores, os demais servidores também tentam interromper a consulta.

Avaliação de expressões de argumentos

Em quase todas as linguagens de programação, para determinados operadores, um dos argumentos pode não ser avaliado. Normalmente, esses operadores são &&, || 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

No processamento distribuído de consultas, o máximo possível de etapas do processamento da consulta é executado em servidores remotos, e as etapas restantes (a mesclagem dos resultados intermediários e tudo o que vem depois) são executadas no servidor solicitante. Isso significa que as funções podem ser executadas em servidores diferentes. Por exemplo, na consulta SELECT f(sum(g(x))) FROM distributed_table GROUP BY h(y),
  • se uma distributed_table tiver 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_table tiver apenas um shard, todas as funções ‘f’, ‘g’ e ‘h’ serão executadas no servidor desse shard.
O resultado de uma função geralmente não depende do servidor em que ela é executada. No entanto, às vezes isso é importante. Por exemplo, funções que trabalham com dicionários usam o dicionário existente no servidor em que estão sendo executadas. Outro exemplo é a função 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 personalizadas com base em expressões lambda podem ser criadas usando a instrução CREATE FUNCTION. Para excluir essas funções, use a instrução DROP FUNCTION.

Funções definidas pelo usuário em WebAssembly

As funções definidas pelo usuário em WebAssembly (WASM UDFs) permitem executar código personalizado compilado em WebAssembly dentro do processo do servidor ClickHouse.

Início rápido

Ative o suporte experimental a WebAssembly na configuração do ClickHouse:
<clickhouse>
    <allow_experimental_webassembly_udf>true</allow_experimental_webassembly_udf>
</clickhouse>
Insira seu módulo WASM compilado na tabela do sistema:
INSERT INTO system.webassembly_modules (name, code)
SELECT 'my_module', base64Decode('AGFzbQEAAAA...');
Crie uma função usando seu módulo WASM:
CREATE FUNCTION my_function
LANGUAGE WASM
ABI ROW_DIRECT
FROM 'my_module'
ARGUMENTS (x UInt32, y UInt32)
RETURNS UInt32;
Use a função nas suas consultas:
SELECT my_function(10, 20);

Mais informações

Consulte a documentação de Funções definidas pelo usuário em WebAssembly para mais detalhes.
Última modificação em 10 de junho de 2026