Пользовательские функции UDF
Выполнимые пользовательские функции
Эта функция поддерживается в приватном превью в ClickHouse Cloud. Пожалуйста, свяжитесь с поддержкой ClickHouse по адресу https://clickhouse.cloud/support для получения доступа.
ClickHouse может вызывать любую внешнюю исполняемую программу или скрипт для обработки данных.
Конфигурация выполняемых пользовательских функций может находиться в одном или нескольких xml-файлах. Путь к конфигурации указывается в параметре user_defined_executable_functions_config.
Конфигурация функции содержит следующие настройки:
name
- имя функции.command
- имя скрипта для выполнения или команда, еслиexecute_direct
равно false.argument
- описание аргумента сtype
и необязательнымname
аргумента. Каждый аргумент описывается в отдельной настройке. Указание имени необходимо, если имена аргументов являются частью сериализации для формата пользовательской функции, такого как Native или JSONEachRow. Значение имени аргумента по умолчанию -c
+ аргумент_номер.format
- формат в котором аргументы передаются команде.return_type
- тип возвращаемого значения.return_name
- имя возвращаемого значения. Указание имени возвращаемого значения необходимо, если имя возвращаемого значения является частью сериализации для формата пользовательской функции, такого как Native или JSONEachRow. Необязательно. Значение по умолчанию -result
.type
- исполняемый тип. Если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
. Необязательный параметр.
Команда должна читать аргументы из STDIN
и выводить результат в STDOUT
. Команда должна обрабатывать аргументы итеративно. То есть после обработки блока аргументов она должна ждать следующий блок.
Примеры
Встроенный скрипт
Создание test_function_sum
, вручную указывая execute_direct
равным 0
с помощью конфигурации XML.
Файл test_function.xml
(/etc/clickhouse-server/test_function.xml
с настройками пути по умолчанию).
Запрос:
Результат:
Скрипт на Python
Читает значение из STDIN
и возвращает его как строку:
Создание test_function
с использованием конфигурации XML.
Файл test_function.xml
(/etc/clickhouse-server/test_function.xml
с настройками пути по умолчанию).
Файл скрипта внутри папки user_scripts
test_function.py
(/var/lib/clickhouse/user_scripts/test_function.py
с настройками пути по умолчанию).
Запрос:
Результат:
Читает два значения из STDIN
и возвращает их сумму как JSON-объект:
Создание test_function_sum_json
с именованными аргументами и форматом JSONEachRow с использованием конфигурации XML.
Файл test_function.xml
(/etc/clickhouse-server/test_function.xml
с настройками пути по умолчанию).
Файл скрипта внутри папки user_scripts
test_function_sum_json.py
(/var/lib/clickhouse/user_scripts/test_function_sum_json.py
с настройками пути по умолчанию).
Запрос:
Результат:
Используйте параметры в настройке command
:
Выполнимые пользовательские функции могут принимать постоянные параметры, настроенные в настройке command
(работает только для пользовательских функций с типом executable
). Это также требует опции execute_direct
(для обеспечения отсутствия уязвимости расширения аргументов оболочки).
Файл test_function_parameter_python.xml
(/etc/clickhouse-server/test_function_parameter_python.xml
с настройками пути по умолчанию).
Файл скрипта внутри папки user_scripts
test_function_parameter_python.py
(/var/lib/clickhouse/user_scripts/test_function_parameter_python.py
с настройками пути по умолчанию).
Запрос:
Результат:
Скрипт оболочки
Скрипт оболочки, который умножает каждое значение на 2:
Выполнимые пользовательские функции могут быть использованы с оболочными скриптами.
Файл test_function_shell.xml
(/etc/clickhouse-server/test_function_shell.xml
с настройками пути по умолчанию).
Файл скрипта внутри папки user_scripts
test_shell.sh
(/var/lib/clickhouse/user_scripts/test_shell.sh
с настройками пути по умолчанию).
Запрос:
Результат:
Обработка ошибок
Некоторые функции могут вызывать исключение, если данные некорректны. В этом случае запрос отменяется, и текст ошибки возвращается клиенту. Для распределенной обработки, когда происходит исключение на одном из серверов, другие серверы также пытаются отменить запрос.
Оценка выражений аргументов
Почти во всех языках программирования один из аргументов может не оцениваться для определенных операторов. Обычно это операторы &&
, ||
и ?:
.
Но в 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-пользовательские функции
Пользовательские функции из лямбда-выражений могут быть созданы с помощью оператора CREATE FUNCTION. Чтобы удалить эти функции, используйте оператор DROP FUNCTION.