Перейти к основному содержимому
Перейти к основному содержимому

Движки таблиц Executable и ExecutablePool

Движки таблиц Executable и ExecutablePool позволяют вам определить таблицу, строки которой создаются с помощью скрипта, который вы определяете (путем записи строк в stdout). Исполняемый скрипт хранится в каталоге users_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 и столбец String с именем comment. Начнем с определения таблицы 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, используя функцию split в Python
  • Результат 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.