Перейти к основному содержанию
Движки таблиц Executable и ExecutablePool позволяют определить таблицу, строки которой генерируются заданным вами скриптом (путём записи строк в stdout). Исполняемый скрипт хранится в каталоге user_scripts и может читать данные из любого источника.
  • Таблицы Executable: скрипт запускается при каждом запросе
  • Таблицы ExecutablePool: поддерживают пул постоянных процессов и используют процессы из этого пула для чтения
При необходимости можно указать один или несколько входных запросов, результаты которых передаются в stdin, откуда их читает скрипт.

Создание таблицы Executable

Для движка таблицы Executable требуются два параметра: имя скрипта и формат входных данных. При необходимости можно также передать один или несколько входных запросов:
Вот соответствующие настройки для таблицы Executable:
  • send_chunk_header
    • Описание: отправляет количество строк в каждом фрагменте перед передачей фрагмента на обработку. Эта настройка позволяет писать скрипт эффективнее, заранее выделяя некоторые ресурсы
    • Значение по умолчанию: false
  • command_termination_timeout
    • Описание: тайм-аут завершения команды в секундах
    • Значение по умолчанию: 10
  • command_read_timeout
    • Описание: тайм-аут чтения данных из stdout команды в миллисекундах
    • Значение по умолчанию: 10000
  • command_write_timeout
    • Описание: тайм-аут записи данных в stdin команды в миллисекундах
    • Значение по умолчанию: 10000
Рассмотрим пример. Следующий скрипт Python называется my_script.py и сохранён в папке user_scripts. Он считывает число i и выводит i случайных строк, причём перед каждой строкой выводится число, отделённое символом табуляции:
Следующая таблица my_executable_table строится на основе вывода my_script.py, который генерирует 10 случайных строк каждый раз, когда вы выполняете SELECT из my_executable_table:
При создании таблицы операция завершается сразу и скрипт не вызывается. При выполнении запроса к my_executable_table скрипт вызывается:

Передача результатов запроса в скрипт

Пользователи сайта Hacker News оставляют комментарии. В Python есть библиотека для обработки естественного языка (nltk) с SentimentIntensityAnalyzer, который позволяет определять, являются ли комментарии положительными, отрицательными или нейтральными, а также присваивать им значение от -1 (очень отрицательный комментарий) до 1 (очень положительный комментарий). Давайте создадим таблицу Executable, которая вычисляет тональность комментариев Hacker News с помощью nltk. В этом примере используется таблица hackernews, описанная здесь. Таблица hackernews включает столбец id типа UInt64 и столбец comment типа String. Начнем с определения таблицы Executable:
Несколько комментариев о таблице sentiment:
  • Файл sentiment.py сохраняется в папке user_scripts (это папка по умолчанию для настройки user_scripts_path)
  • Формат TabSeparated означает, что наш Python-скрипт должен генерировать строки исходных данных со значениями, разделёнными табуляцией
  • Запрос выбирает два столбца из hackernews. Python-скрипту потребуется разобрать значения этих столбцов из входящих строк
Вот определение sentiment.py:
Несколько комментариев о нашем Python-скрипте:
  • Чтобы это работало, вам нужно выполнить nltk.downloader.download('vader_lexicon'). Это можно было бы добавить в скрипт, но тогда загрузка выполнялась бы при каждом запросе к таблице sentiment, а это неэффективно
  • Каждое значение row будет отдельной строкой в результирующем наборе запроса SELECT id, comment FROM hackernews WHERE id > 0 AND comment != '' LIMIT 20
  • Входящая строка разделена символами табуляции, поэтому мы разбираем id и comment с помощью функции Python split
  • Результат polarity_scores — это объект JSON с несколькими значениями. Мы решили просто взять значение compound из этого объекта JSON
  • Помните, что таблица sentiment в ClickHouse использует формат TabSeparated и содержит два столбца, поэтому функция print разделяет эти столбцы табуляцией
Каждый раз, когда вы пишете запрос, выбирающий строки из таблицы sentiment, выполняется запрос SELECT id, comment FROM hackernews WHERE id > 0 AND comment != '' LIMIT 20, а его результат передаётся в sentiment.py. Давайте проверим:
Ответ будет выглядеть так:

Создание таблицы ExecutablePool

Синтаксис ExecutablePool похож на Executable, но у таблицы ExecutablePool есть несколько важных настроек, которые доступны только для неё:
  • pool_size
    • Описание: Размер пула процессов. Если размер равен 0, ограничения по размеру отсутствуют
    • Значение по умолчанию: 16
  • max_command_execution_time
    • Описание: Максимальное время выполнения команды в секундах
    • Значение по умолчанию: 10
Мы можем легко преобразовать приведённую выше таблицу sentiment, чтобы использовать ExecutablePool вместо Executable:
ClickHouse будет по мере необходимости поддерживать 4 процесса при выполнении клиентом запросов к таблице sentiment_pooled.
Последнее изменение 2 июля 2026 г.