- исполняемые пользовательские функции запускают внешнюю программу или скрипт (Python, Bash и т. д.) и потоково передают им блоки данных через STDIN / STDOUT. Используйте их для интеграции существующего кода или инструментов без перекомпиляции ClickHouse. По сравнению с внутрипроцессными вариантами у них выше накладные расходы на каждый вызов, поэтому они лучше подходят для более сложной логики или случаев, когда нужна другая среда выполнения.
- пользовательские функции SQL определяются с помощью
CREATE FUNCTIONисключительно на SQL. Они подставляются/разворачиваются в план запроса (без отдельного процесса), что делает их лёгкими и идеально подходящими для повторного использования логики выражений или упрощения сложных вычисляемых столбцов. - Экспериментальные пользовательские функции WebAssembly выполняют код, скомпилированный в WebAssembly, внутри песочницы в процессе сервера. Они обеспечивают меньшие накладные расходы на каждый вызов, чем внешние исполняемые файлы, и лучшую изоляцию, чем нативные расширения, что делает их подходящими для пользовательских алгоритмов, написанных на языках, которые можно компилировать в WASM (например, C/C++/Rust).
- Экспериментальные исполняемые пользовательские функции на основе драйвера позволяют предоставляемому оператором “драйверу” преобразовывать фрагмент кода, указанный в
CREATE FUNCTION ... ENGINE = DriverName(...) AS '...', в исполняемую пользовательскую функцию при создании функции (например, путём компиляции). Они основаны на исполняемых пользовательских функциях и требуют серверной конфигурации драйвера.
Исполняемые пользовательские функции
В ClickHouse Cloud исполняемые UDF находятся в публичной бета-версии и создаются через интерфейс консоли Cloud. См. Пользовательские функции в Cloud, чтобы ознакомиться со специальным процессом для Cloud.
user_defined_executable_functions_config.
Конфигурация функции включает следующие настройки:
Команда должна читать аргументы из
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.
Пользовательские функции SQL
Пользовательские функции WebAssembly
Быстрый старт
Дополнительная информация
Исполняемые пользовательские функции на базе драйверов
Это экспериментальная возможность, которая в будущих релизах может измениться с нарушением обратной совместимости. Включите её с помощью настройки сервера
allow_experimental_executable_udf_drivers.ENGINE = DriverName(...), ClickHouse запускает create_command драйвера, передавая ему сигнатуру функции и тело кода; драйвер компилирует тело или иным образом его обрабатывает и выводит конфигурацию исполняемой пользовательской функции, которую ClickHouse затем сохраняет и загружает.
Это позволяет администраторам дать пользователям безопасный и строго ограниченный способ определять функции на произвольном языке (например, на C, компилируемом внутри изолированного контейнера), не предоставляя им доступ к конфигурационным файлам или файловой системе сервера. Набор доступных драйверов полностью контролируется оператором.
Включение драйверов
-
Установите экспериментальный флаг в конфигурации сервера:
-
Укажите в
user_defined_executable_function_drivers_configодин или несколько файлов конфигурации драйверов (поддерживаются glob-шаблоны) и при необходимости задайтеdynamic_user_defined_executable_functions_path— каталог, где хранятся сгенерированные конфигурации исполняемых UDF:
SYSTEM RELOAD CONFIG, поэтому драйверы можно добавлять, изменять или удалять без перезапуска сервера.
Конфигурация драйвера
<driver>. Поддерживаются следующие поля:
Пример конфигурации драйвера:
Контракт вызова драйвера
CREATE FUNCTION вызывается create_command с заданными переменными env и следующими аргументами:
--name <function_name>--return <return_type>(если указана секцияRETURNS)--args <signature>(если указана секцияARGUMENTS), где signature — это объявленный список аргументов, напримерx UInt8, y DateTime--<key> <value>для каждого объявленного аргумента движка, указанного вENGINE = DriverName(key = value)
AS) передаётся на стандартный ввод команды. Команда должна вывести конфигурацию исполняемой UDF в стандартный вывод. Формат определяется автоматически: вывод, начинающийся с <, обрабатывается как XML, иначе — как YAML. Имя функции, заданное в сгенерированной конфигурации, должно совпадать с именем создаваемой функции. Если create_command завершается с ненулевым кодом выхода, оператор завершается ошибкой с исключением, включающим код выхода и содержимое стандартного потока ошибок драйвера.
drop_command, если он указан, вызывается таким же образом (без тела кода в stdin) при удалении функции.
Создание FUNCTION
create_command драйвера, записывает сгенерированную конфигурацию в dynamic_user_defined_executable_functions_path, после чего её подхватывает существующий загрузчик исполняемых UDF. После этого функцию можно вызывать как и любую другую функцию.
Удаление функции
DROP FUNCTION вызывает drop_command драйвера (если она задана), удаляет сгенерированную динамическую конфигурацию и отдельный рабочий каталог функции, перезагружает загрузчик исполняемых UDF и удаляет сохранённый запрос.
Сохранение и перезапуск
ATTACH FUNCTION ... в каталоге пользовательских SQL-объектов, поэтому функция сохраняется после перезапуска сервера. При запуске сгенерированные конфигурации из dynamic_user_defined_executable_functions_path загружаются напрямую, без повторного запуска драйвера. Если для сохранённого ATTACH FUNCTION нет соответствующей сгенерированной конфигурации (например, если динамический каталог был утерян), драйвер запускается повторно, чтобы создать её заново.
Ограничения
- Эта возможность экспериментальная и доступна только при включении
allow_experimental_executable_udf_drivers. - Исполняемые UDF на базе драйверов не поддерживаются с реплицируемым хранилищем пользовательских функций (
ON CLUSTERи<user_defined_zookeeper_path>), поскольку реплицируется только исходный запрос, а не сгенерированные артефакты. RESTOREисполняемого UDF на базе драйверов из резервной копии сохраняет запрос, но не запускает драйвер повторно; сгенерированная конфигурация материализуется позже в процессе восстановления при перезапуске.
Пример драйверов на C
programs/server/user_defined_executable_function_drivers_config.d/, которые компилируют и выполняют тело функции на C. Это лишь примеры, и пакеты их не устанавливают:
DockerC- компилирует и выполняет код внутри изолированных контейнеров Docker (--network=none --read-only --cap-drop=ALL --security-opt=no-new-privileges, а также с ограничениями по памяти/CPU/PID), создавая UDFexecutable_pool.GVisorC- вариант, запускающий скомпилированный бинарный файл в среде выполненияrunscот gVisor.UnsafeC- компилирует и выполняет код напрямую на хосте, без песочницы. Как следует из названия, он не обеспечивает никакой изоляции и предназначен только для доверенных окружений и тестирования.