Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Движок таблицы QueryRunner

Записи, вставленные в таблицу QueryRunner, представляют собой запросы, которые выполняет движок. Движок можно использовать для асинхронного выполнения запросов, батчевого выполнения сгенерированных запросов, отправки запросов в удаленные кластеры, запуска бенчмарков, фаззинга и тестирования с теневым трафиком.

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

CREATE TABLE runner
(
    query String,
    database String,
    settings Map(LowCardinality(String), String)
)
ENGINE = QueryRunner
SETTINGS
    cluster = 'cluster_name',
    shard = '1',
    mode = 'asynchronous',
    threads = 4,
    max_queue_size = 1000
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER | NONE }];

Таблица должна быть создана с подмножеством допустимых столбцов: query, database, settings. Столбец query обязателен, остальные столбцы — необязательны.

Столбец Type Значение
query String Запрос, который нужно выполнить.
database String База данных по умолчанию для запроса. Если значение пустое, используется база данных сервера по умолчанию.
settings Map(String, String) Настройки, применяемые к запросу.

Настройки движка

Setting Default Meaning
cluster '' Имя кластера, в который отправляются запросы. Если значение пустое, запросы выполняются локально.
shard '1' Индекс сегмента кластера, начиная с 1, в который отправляются запросы, или 'random' для выбора случайного сегмента для каждого запроса, или 'all', чтобы выполнять каждый запрос на каждом сегменте. Требует настройки cluster.
mode 'asynchronous' В режиме synchronous INSERT возвращает управление после завершения всех запросов из вставленного батча. В режиме asynchronous INSERT возвращает управление, как только запросы поставлены в очередь.
threads 4 Количество фоновых потоков, выполняющих запросы.
max_queue_size 1000 Максимальное количество запросов в очереди. Когда очередь заполнена, новые запросы отбрасываются, а ошибка записывается в журнал.

Подробности

Таблица допускает только запросы INSERT. Запросы выполняются в режиме "fire and forget": в случае исключения повторных попыток не выполняется, а результаты запросов SELECT отбрасываются (единственный способ сохранить результаты — INSERT SELECT). Успешность каждого запроса можно проверить в таблице system.query_log, где запросы, инициированные этим движком, помечаются как is_internal = 1 на инициирующем сервере.

Поставленные в очередь запросы хранятся в памяти и не сохраняются после перезапуска сервера. При остановке сервера (или DROP/DETACH таблицы) запросы, которые еще не начали выполняться, отбрасываются. Из запросов, которые уже выполняются, отправленные в кластер отменяются, а выполняющиеся локально продолжают выполняться до завершения.

Если выполняемый запрос сам является INSERT, его данные должны быть указаны прямо в нем — INSERT ... VALUES (...), INSERT ... SELECT ... или INSERT ... FORMAT ... с данными в тексте запроса. INSERT, который ожидает данные из отдельного потока, не поддерживается.

Локальный режим и безопасность SQL

Без настройки cluster запросы выполняются на локальном сервере. Пользователь, от имени которого они выполняются, определяется конструкцией безопасность SQL:

  • INVOKER (по умолчанию): запросы выполняются от имени пользователя, который выполнил INSERT.
  • DEFINER: запросы выполняются от имени указанного пользователя DEFINER. Поскольку такие запросы могут быть произвольными, предоставление INSERT на такую таблицу делегирует все привилегии пользователя DEFINER.
  • NONE: запросы выполняются с полным доступом, без пользователя. При создании таблицы требуется grant ALLOW_SQL_SECURITY_NONE.

Режим кластера

Когда указана настройка cluster, запросы отправляются в указанный кластер.

Целевой сегмент выбирается с помощью shard: это может быть фиксированный индекс с нумерацией с 1 (по умолчанию '1'), 'random' для выбора случайного сегмента для каждого запроса или 'all' для выполнения каждого запроса на каждом сегменте кластера. Реплика внутри сегмента выбирается в соответствии с настройкой load_balancing сервера.

Столбец database задаёт базу данных по умолчанию для соединения с удалённым сервером. Поскольку база данных по умолчанию задаётся один раз для каждого соединения, каждое отдельное значение database использует собственный пул соединений, который создаётся при первом использовании и затем повторно используется в течение всего времени жизни таблицы.

DEFINER и безопасность SQL действуют только в локальном режиме, а их сочетание с настройкой cluster приводит к ошибке. На удалённых серверах запросы проходят аутентификацию с использованием учётных данных из конфигурации кластера и выполняются как обычные исходные запросы: они записываются в system.query_log с is_initial_query = 1 и собственным query_id (не связанным с INSERT, который их создал). На инициирующем сервере отправленные запросы записываются в system.query_log с is_internal = 1.

Поскольку движок отбрасывает результаты запросов, он всегда выполняет отправленные запросы с discard_query_data = 1, поэтому данные результата SELECT-запросов не передаются по сети (это переопределяет любое значение discard_query_data, заданное в столбце settings).

Ожидание завершения запросов

В асинхронном режиме можно использовать следующий запрос, чтобы блокировать выполнение до тех пор, пока не завершатся все запросы, к этому моменту отправленные в таблицу:

SYSTEM WAIT QUERY RUNNER runner;

Пример

Повторное выполнение последних запросов SELECT из журнала запросов:

INSERT INTO runner (query, database, settings)
SELECT query, current_database, Settings
FROM system.query_log
WHERE type = 'QueryFinish' AND is_initial_query AND NOT is_internal AND query_kind = 'Select'
  AND event_time > now() - INTERVAL 1 HOUR;
Navigation