Пользовательские функции (UDF) позволяют расширять возможности ClickHouse сверх того, что доступно в более чем тысяче готовых функций.
В ClickHouse Cloud есть несколько способов создавать пользовательские функции и управлять ими:
- С помощью SQL
- С помощью интерфейса и собственного кода (публичная бета)
- С помощью Cloud API (бета)
- С помощью Terraform (бета)
Пользовательские функции SQL
Пользовательские функции SQL можно создавать с помощью оператора CREATE FUNCTION на основе лямбда-выражения.
В этом примере мы создадим простую исполняемую пользовательскую функцию isBusinessHours.
Функция будет проверять, попадает ли указанная временная метка в стандартные рабочие часы, и возвращать true, если да, и false — если нет.
- Войдите в Cloud Console и откройте консоль SQL
- Напишите следующий SQL-запрос, чтобы создать функцию
isBusinessHours:
CREATE FUNCTION isBusinessHours AS (ts) ->
toDayOfWeek(ts) BETWEEN 1 AND 5
AND toHour(ts) BETWEEN 9 AND 17;- Чтобы протестировать только что созданную UDF, выполните следующую команду:
SELECT isBusinessHours('2026-03-20 10:00:00'::DateTime), isBusinessHours('2026-03-20 23:00:00'::DateTime);Вы должны получить такой результат:
1 0- Вы можете использовать команду
DROP FUNCTION, чтобы удалить только что созданную UDF:
DROP FUNCTION isBusinessHoursЭто означает:
- Настройки уровня сеанса (заданные через оператор
SET) не передаются в контекст выполнения UDF - Настройки профиля пользователя не наследуются UDF
- Настройки уровня запроса не применяются при выполнении UDF
Пользовательские функции, созданные через интерфейс
ClickHouse Cloud позволяет создавать пользовательские функции через интерфейс.
В этом примере мы создадим ту же простую исполняемую пользовательскую функцию isBusinessHours, которая проверяет, попадает ли заданная временная метка в обычные рабочие часы.
Ранее мы создавали её с помощью SQL, а на этот раз создадим её с помощью Python и настроим через интерфейс.
Создайте Python-файл
Создайте новый файл main.py на локальной машине:
cat > main.py << 'EOF'
import sys
from datetime import datetime
for line in sys.stdin:
ts = datetime.fromisoformat(line.strip())
result = 1 if (0 <= ts.weekday() <= 4 and 9 <= ts.hour <= 17) else 0
print(result)
sys.stdout.flush()
EOFЕсли ваш Python-скрипт импортирует сторонние пакеты, перечислите их в файле requirements.txt, и ClickHouse Cloud установит их автоматически. Вместо этого можно добавить зависимости прямо в ZIP-архив, но тогда потребуется включить кэшированные пакеты для обеих архитектур CPU, поэтому вариант с requirements.txt проще. Например:
requests>=2.28.0
numpy>=1.23.0Пакеты зависимостей и локальные файлы
Чтобы включить пакеты зависимостей и любые дополнительные локальные файлы (например, wheel-файлы, файлы конфигурации или файлы данных), поместите их в тот же каталог, где находятся main.py и requirements.txt. При создании ZIP-архива включите в него все файлы:
zip is_business_hours.zip main.py requirements.txtВ коде Python вы можете сослаться на базовый каталог локального упакованного path, используя os.path.dirname(os.path.abspath(__file__)). Это возвращает абсолютный path к каталогу, в котором находится ваш main.py внутри ZIP-архива, что позволяет получать доступ к другим упакованным файлам:
import os
# Get the base directory of the bundled files
base_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(base_dir, 'config.json')Это полезно, когда вам нужно:
- Получить доступ к файлам конфигурации, включённым в ваш UDF
- Загрузить wheel-пакеты для пользовательских зависимостей
- Указать дополнительные скрипты или файлы данных
Теперь сожмите файл в ZIP-архив:
zip is_business_hours.zip main.pyСоздание UDF через интерфейс
- На главной странице Cloud Console нажмите имя вашей организации в меню в левом нижнем углу.
- Выберите в меню Пользовательские функции.
- На странице пользовательских функций нажмите Настроить UDF. Справа откроется панель конфигурации.
- Введите имя функции. В этом примере используйте
isBusinessHours. - Выберите тип функции: Executable pool или Executable:
- Executable pool: Поддерживается пул постоянных процессов, и для операций чтения процесс берётся из этого пула.
- Executable: Скрипт запускается для каждого запроса.
- В этом примере используйте настройки по умолчанию. Полный список параметров конфигурации см. в разделе Исполняемые пользовательские функции.
- Нажмите Выбрать файл, чтобы загрузить файл
.zip, созданный в начале этого руководства. - Добавьте новый аргумент. В этом примере добавьте аргумент
timestampс типомDateTime. - Выберите тип возвращаемого значения. В этом примере выберите
Bool. - Нажмите Создать UDF. В диалоговом окне отобразится текущий статус сборки.
- Если возникнут какие-либо проблемы, статус изменится на ошибка.
- В противном случае статус последовательно изменится с сборка на подготовка. Для завершения подготовки ваш сервис должен быть активен. Если сервис находится в состоянии бездействия, нажмите Пробудить сервис на панели Сведения о UDF рядом с именем сервиса.
- После завершения статус изменится на развернуто.
Протестируйте свою UDF
- вернитесь на главную страницу SQL Console, нажав в левом верхнем углу страницы Settings - return to your service view
- нажмите SQL Console в меню слева
- введите следующий запрос:
SELECT isBusinessHours('2026-03-20 10:00:00'::DateTime), isBusinessHours('2026-03-20 23:00:00'::DateTime);Вы увидите результат:
true falseСоздайте новую версию
Чтобы изменить код UDF, создайте новую версию. Панель Edit управляет только тем, каким сервисам назначена UDF; загрузка файла в этой панели не заменит уже развернутый код.
- На главной странице Cloud Console нажмите имя своей организации в меню в левом нижнем углу.
- В меню выберите Пользовательские функции.
- Для UDF
isBusinessHoursнажмите на три точки в разделе Действия, затем выберите Создать новую версию - Загрузите ZIP-архив с измененным кодом или измените настройки, затем нажмите Создать новую версию
Вы успешно добавили свою первую пользовательскую функцию через интерфейс, убедились, что она выполняется, и узнали, как при необходимости создать для нее новую версию.
Управление пользовательскими функциями (UDF) через Cloud API
Всё, что доступно в интерфейсе, также доступно программно через ClickHouse Cloud API. Конечные точки UDF позволяют автоматизировать весь жизненный цикл UDF: загрузку исходных архивов, создание функций и версий, их подключение к сервисам и удаление.
Типичный процесс создания и развертывания UDF через API:
- Создайте URL для загрузки, чтобы получить предварительно подписанный URL для загрузки
application/zip, а затем загрузите по нему ZIP-архив. Каждый ID загрузки можно использовать только для одной попытки создания UDF или её версии; при повторной попытке запросите новый URL для загрузки. - Создайте UDF из загруженного архива, указав имя функции, среду выполнения, аргументы и возвращаемый тип.
- Подключите UDF к сервису. Если версия не указана, подключается последняя готовая версия. Сервис должен быть запущен; бездействующие сервисы можно предварительно активировать.
Полный список конечных точек:
| Конечная точка | Описание |
|---|---|
| Создать URL для загрузки UDF | Создаёт предварительно подписанный URL для загрузки application/zip, действующий в пределах организации |
| Создать UDF | Создаёт новую UDF из загруженного архива |
| Получить список пользовательских функций (UDF) | Возвращает последнюю версию каждой UDF в организации |
| Получить UDF | Возвращает последнюю версию UDF |
| Удалить UDF | Удаляет все версии UDF и отключает её от всех сервисов |
| Создать версию UDF | Принимает исходный архив, назначает версию и запускает сборку UDF |
| Получить список версий UDF | Возвращает все версии UDF |
| Удалить версию UDF | Удаляет версию UDF, не подключённую ни к одному сервису |
| Подключить UDF к сервису | Подключает одну версию UDF к сервису, при необходимости заменяя текущую версию |
| Получить список подключений UDF | Возвращает текущие подключения UDF к сервисам |
| Получить подключение UDF | Возвращает текущее подключение UDF к одному сервису |
| Отключить UDF от сервиса | Отключает UDF от сервиса |
См. справочник API UDF со схемами запросов и ответов.
Управление пользовательскими функциями (UDF) с помощью Terraform
Официальный Terraform-провайдер ClickHouse включает два ресурса для управления пользовательскими функциями (UDF) в рамках подхода «инфраструктура как код»:
clickhouse_udfуправляет самой функцией. Он принимает ZIP-архив с исходным кодом функции и публикует новую версию при изменении хеша архива, дожидаясь завершения сборки.clickhouse_udf_attachmentподключает версию UDF к сервису. К сервису можно одновременно подключить не более одной версии функции. Можно закрепить конкретный номер версии или сослаться наclickhouse_udf.<name>.version, чтобы автоматически обновлять сервисы до последней версии.
Например, чтобы развернуть с помощью Terraform UDF isBusinessHours из предыдущего примера:
resource "clickhouse_udf" "is_business_hours" {
function_name = "isBusinessHours"
runtime = "python3.11"
type = "executable_pool"
return_type = "Bool"
arguments = [
{ name = "timestamp", type = "DateTime" },
]
source_archive_path = "${path.module}/is_business_hours.zip"
source_archive_hash = filebase64sha256("${path.module}/is_business_hours.zip")
}
resource "clickhouse_udf_attachment" "production" {
function_name = clickhouse_udf.is_business_hours.function_name
service_id = var.service_id
version = clickhouse_udf.is_business_hours.version
}Подключение возможно только для версий в состоянии готовности и может занять несколько минут; бездействующие сервисы запускаются автоматически. При удалении ресурса clickhouse_udf удаляются все версии функции, и она отключается от всех сервисов.