Learning Platform
Глоссарий Troubleshooting
Урок 13.08 · 30 мин
Продвинутый
max_rows_to_readmax_result_rowsmax_execution_timequotasSETTINGS

Query Governance: ограничения и квоты

В production-системах ClickHouse одновременно работают десятки аналитиков, ETL-задач и дашбордов. Без контроля один неоптимальный запрос — полный скан 100-миллиардной таблицы без фильтра по партиции — способен исчерпать RAM-сервера и вытеснить остальные запросы. Query governance — это набор механизмов ClickHouse, которые задают жёсткие лимиты на ресурсы, время выполнения и объём результатов: на уровне отдельного запроса, пользователя, роли или временного интервала.


Лимиты на уровне запроса

Самый прямой механизм защиты — задать ограничения непосредственно в SETTINGS-секции запроса.

max_rows_to_read

Ограничивает число строк, которые ClickHouse может прочитать для выполнения запроса. При превышении — ошибка TOO_MANY_ROWS.

-- Запрос сканирует не более 1 млн строк
SELECT count()
FROM huge_table
SETTINGS max_rows_to_read = 1000000;

Это ограничение проверяется на уровне сканирования (до агрегации), что делает его эффективным инструментом для предотвращения случайных полных сканов.

max_result_rows

Ограничивает число строк в итоговом результате. При превышении — ошибка TOO_MANY_ROWS_OR_BYTES.

-- Результат не может содержать более 10 000 строк
SELECT user_id, event_type, count() AS cnt
FROM events
GROUP BY user_id, event_type
SETTINGS max_result_rows = 10000;

max_execution_time

Максимальное время выполнения запроса в секундах. При превышении — ошибка TIMEOUT_EXCEEDED.

-- Запрос будет остановлен через 30 секунд
SELECT sum(price)
FROM orders
WHERE region = 'EU'
SETTINGS max_execution_time = 30;
WARNING

max_execution_time — мягкий лимит. Проверка таймаута происходит при чтении следующего блока данных. Один тяжёлый блок (например, сложный JOIN с десятками миллионов строк) может задержать отмену на несколько секунд после истечения таймаута. Для жёстких realtime требований дополнительно используйте max_rows_to_read.

max_result_bytes

Ограничивает размер результата в байтах. Удобно для защиты от запросов, возвращающих слишком большие текстовые блоки.

-- Результат не более 100 МБ
SELECT *
FROM logs
WHERE level = 'ERROR'
SETTINGS max_result_bytes = 104857600;

Комбинирование настроек

Несколько ограничений можно задать в одной SETTINGS-секции:

SELECT query_id, memory_usage, read_rows
FROM system.query_log
WHERE type = 'QueryFinish'
SETTINGS
    max_threads = 4,
    max_execution_time = 30,
    max_result_rows = 1000;

Ограничения на уровне роли

Задавать лимиты в каждом запросе неудобно и ненадёжно — аналитик может их убрать. Надёжнее зафиксировать ограничения в роли пользователя.

-- Создать роль с ограничением на число строк результата
CREATE ROLE analyst_role SETTINGS max_result_rows = 10000;

-- Назначить роль пользователю
GRANT analyst_role TO analyst_user;

Теперь пользователь analyst_user не сможет получить более 10 000 строк в одном запросе, даже если попытается переопределить настройку через SETTINGS.

-- Создать роль для ETL с ограничением времени
CREATE ROLE etl_role SETTINGS max_execution_time = 300;
GRANT etl_role TO etl_service;

Квоты (QUOTA)

Квоты ограничивают потребление ресурсов за временной интервал — в отличие от max_result_rows (per-query лимит), квота накапливается и сбрасывается по расписанию.

Синтаксис CREATE QUOTA

-- Квота: не более 1 млн строк результата в сутки
CREATE QUOTA daily_quota
    FOR INTERVAL 1 DAY MAX result_rows = 1000000
    TO analyst_role;
-- Квота с несколькими интервалами
CREATE QUOTA reporting_quota
    FOR INTERVAL 10 SECOND MAX result_rows = 10
    FOR INTERVAL 1 HOUR MAX result_rows = 100000
    FOR INTERVAL 1 DAY MAX result_rows = 1000000
    TO reporter_role;

При исчерпании квоты следующий запрос, превышающий лимит, получает ошибку QUOTA_EXCEEDED.

Просмотр квот

-- Текущие квоты в системе
SHOW QUOTAS;

-- Использование квоты конкретным пользователем
SELECT *
FROM system.quota_usage;

Сравнение механизмов governance

ОграничениеScopeОшибка при превышенииПример
max_rows_to_readPer-query, на уровне сканированияTOO_MANY_ROWSSETTINGS max_rows_to_read = 1e6
max_result_rowsPer-query, на уровне результатаTOO_MANY_ROWS_OR_BYTESSETTINGS max_result_rows = 10000
max_execution_timePer-query, по времениTIMEOUT_EXCEEDEDSETTINGS max_execution_time = 30
max_result_bytesPer-query, по размеру результатаTOO_MANY_ROWS_OR_BYTESSETTINGS max_result_bytes = 1e8
Role SETTINGSPer-role, для всех запросов пользователяЗависит от настройкиCREATE ROLE r SETTINGS max_result_rows = 1000
QUOTA FOR INTERVALНакопительный лимит за периодQUOTA_EXCEEDEDFOR INTERVAL 1 DAY MAX result_rows = 1e6

Ключевые выводы

  1. max_rows_to_read защищает от случайных full-scan запросов — ошибка TOO_MANY_ROWS возникает до агрегации, на уровне сканирования.
  2. max_execution_time задаёт таймаут в секундах, но является мягким лимитом: проверка происходит между блоками, не внутри обработки блока.
  3. Role-level SETTINGS надёжнее per-query SETTINGS: пользователь не может превысить ограничение, заданное в роли.
  4. CREATE QUOTA FOR INTERVAL ограничивает суммарное потребление за временной период — в отличие от per-query лимитов, квота накапливается между запросами.
  5. Комбинируйте механизмы: per-query SETTINGS для ad-hoc защиты, роли для системного управления, квоты для fair-use политики.
Мониторинг блокировок и долгих запросов в PostgreSQL Resource governance в data platforms: quotas, priorities и fair scheduling

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 3. Аналитик жалуется, что его запрос к таблице events обрывается с ошибкой TIMEOUT_EXCEEDED примерно через 30 секунд, хотя он не задавал никаких ограничений в своём запросе. Какая настройка роли или пользователя, скорее всего, вызывает это поведение?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 10