- исполняемые пользовательские функции запускают внешнюю программу или скрипт (Python, Bash и т. д.) и потоково передают им блоки данных через STDIN / STDOUT. Используйте их для интеграции существующего кода или инструментов без перекомпиляции ClickHouse. По сравнению с внутрипроцессными вариантами у них выше накладные расходы на каждый вызов, поэтому они лучше подходят для более сложной логики или случаев, когда нужна другая среда выполнения.
- пользовательские функции SQL определяются с помощью
CREATE FUNCTIONисключительно на SQL. Они подставляются/разворачиваются в план запроса (без отдельного процесса), что делает их лёгкими и идеально подходящими для повторного использования логики выражений или упрощения сложных вычисляемых столбцов. - Экспериментальные пользовательские функции WebAssembly выполняют код, скомпилированный в WebAssembly, внутри песочницы в процессе сервера. Они обеспечивают меньшие накладные расходы на каждый вызов, чем внешние исполняемые файлы, и лучшую изоляцию, чем нативные расширения, что делает их подходящими для пользовательских алгоритмов, написанных на языках, которые можно компилировать в WASM (например, C/C++/Rust).
Исполняемые пользовательские функции
Эта возможность доступна в рамках закрытой предварительной версии в ClickHouse Cloud.
Чтобы получить доступ, обратитесь в ClickHouse Support: https://clickhouse.cloud/support.
user_defined_executable_functions_config.
Конфигурация функции включает следующие настройки:
| Параметр | Описание | Обязательно | Значение по умолчанию |
|---|---|---|---|
name | Имя функции | Да | - |
command | Имя скрипта для выполнения или команда, если execute_direct имеет значение false | Да | - |
argument | Описание аргумента с указанием type и необязательного name. Каждый аргумент задается отдельной настройкой. Указывать имя необходимо, если имена аргументов входят в сериализацию формата пользовательской функции, такого как Native или JSONEachRow | Да | c + argument_number |
format | Формат, в котором аргументы передаются команде. Ожидается, что вывод команды также будет в этом формате | Да | - |
return_type | Тип возвращаемого значения | Да | - |
return_name | Имя возвращаемого значения. Указывать его необходимо, если оно входит в сериализацию формата пользовательской функции, такого как Native или JSONEachRow | Необязательно | result |
type | Тип executable. Если для type задано значение executable, запускается одна команда. Если задано значение executable_pool, создается пул команд | Да | - |
max_command_execution_time | Максимальное время выполнения обработки блока данных в секундах. Эта настройка применима только к командам executable_pool | Необязательно | 10 |
command_termination_timeout | Время в секундах, в течение которого команда должна завершиться после закрытия ее канала. По истечении этого времени процессу, выполняющему команду, отправляется SIGTERM | Необязательно | 10 |
command_read_timeout | Тайм-аут чтения данных из stdout команды в миллисекундах | Необязательно | 10000 |
command_write_timeout | Тайм-аут записи данных в stdin команды в миллисекундах | Необязательно | 10000 |
pool_size | Размер пула команд | Необязательно | 16 |
send_chunk_header | Определяет, нужно ли отправлять количество строк перед передачей фрагмента данных процессу | Необязательно | false |
execute_direct | Если execute_direct = 1, command будет искаться в каталоге user_scripts, указанном в user_scripts_path. Дополнительные аргументы скрипта можно указать, разделив их пробелами. Пример: script_name arg1 arg2. Если execute_direct = 0, command передается как аргумент в bin/sh -c | Необязательно | 1 |
lifetime | Интервал перезагрузки функции в секундах. Если задано значение 0, функция не перезагружается | Необязательно | 0 |
deterministic | Является ли функция детерминированной (возвращает один и тот же результат для одних и тех же входных данных) | Необязательно | false |
stderr_reaction | Как обрабатывать вывод команды в stderr. Значения: none (игнорировать), log (сразу записывать весь stderr в лог), log_first (записывать в лог первые 4 KiB после завершения), log_last (записывать в лог последние 4 KiB после завершения), throw (немедленно сгенерировать исключение при любом выводе в stderr). При использовании log_first или log_last с ненулевым кодом выхода содержимое stderr включается в сообщение об исключении | Необязательно | log_last |
check_exit_code | Если true, ClickHouse проверяет код завершения команды. Ненулевой код завершения вызывает исключение | Необязательно | true |
STDIN и выводить результат в STDOUT. Команда должна обрабатывать аргументы итеративно. То есть после обработки одного фрагмента аргументов она должна ждать следующий.
Исполняемые пользовательские функции
Примеры
UDF из встроенного скрипта
test_function_sum, вручную задав execute_direct значение 0, с помощью конфигурации XML или YAML.
- XML
- YAML
Файл
test_function.xml (/etc/clickhouse-server/test_function.xml при настройках пути по умолчанию)./etc/clickhouse-server/test_function.xml
Query
Result
UDF из скрипта Python
STDIN и возвращает его в виде строки.
Создайте test_function, используя конфигурацию XML или YAML.
- XML
- YAML
Файл
test_function.xml (/etc/clickhouse-server/test_function.xml при использовании путей по умолчанию)./etc/clickhouse-server/test_function.xml
Создайте файл скрипта
test_function.py в папке user_scripts (/var/lib/clickhouse/user_scripts/test_function.py при использовании путей по умолчанию).
Query
Result
Прочитайте два значения из STDIN и верните их сумму в виде объекта JSON
test_function_sum_json с именованными аргументами и форматом JSONEachRow, используя конфигурацию в XML или YAML.
- XML
- YAML
Файл
test_function.xml (/etc/clickhouse-server/test_function.xml при настройках путей по умолчанию)./etc/clickhouse-server/test_function.xml
Создайте файл скрипта
test_function_sum_json.py в папке user_scripts (/var/lib/clickhouse/user_scripts/test_function_sum_json.py при настройках путей по умолчанию).
Query
Result
Использование параметров в настройке command
executable могут принимать константные параметры, заданные в настройке command (это работает только для пользовательских функций типа executable).
Также требуется параметр execute_direct, чтобы исключить уязвимость, связанную с подстановкой аргументов командной оболочкой.
- XML
- YAML
Файл
test_function_parameter_python.xml (/etc/clickhouse-server/test_function_parameter_python.xml, если используются пути по умолчанию)./etc/clickhouse-server/test_function_parameter_python.xml
Создайте файл скрипта
test_function_parameter_python.py в каталоге user_scripts (/var/lib/clickhouse/user_scripts/test_function_parameter_python.py, если используются пути по умолчанию).
Query
Result
UDF из shell-скрипта
- XML
- YAML
Файл
test_function_shell.xml (/etc/clickhouse-server/test_function_shell.xml при пути по умолчанию)./etc/clickhouse-server/test_function_shell.xml
Создайте файл скрипта
test_shell.sh в папке user_scripts (/var/lib/clickhouse/user_scripts/test_shell.sh при пути по умолчанию).
/var/lib/clickhouse/user_scripts/test_shell.sh
Query
Result
Обработка ошибок
Вычисление выражений аргументов
&&, || и ?:.
В ClickHouse аргументы функций (операторов) вычисляются всегда.
Это связано с тем, что вычисляются сразу целые части столбцов, а не каждая строка отдельно.
Выполнение функций при распределённой обработке запросов
SELECT f(sum(g(x))) FROM distributed_table GROUP BY h(y),
- если
distributed_tableсодержит как минимум два сегмента, функции ‘g’ и ‘h’ выполняются на удалённых серверах, а функция ‘f’ — на сервере-инициаторе запроса. - если
distributed_tableсодержит только один сегмент, все функции ‘f’, ‘g’ и ‘h’ выполняются на сервере этого сегмента.
hostName, которая возвращает имя сервера, на котором она выполняется, чтобы можно было использовать GROUP BY по серверам в запросе SELECT.
Если функция в запросе выполняется на сервере-инициаторе запроса, но её нужно выполнить на удалённых серверах, можно обернуть её в агрегатную функцию ‘any’ или добавить в ключ GROUP BY.