Spark

Средний уровень

Почему утилизация кластера Spark низкая, хотя задача успешно завершается?

«Завершилось без ошибок» и «мы использовали кластер, за который платим» — два разных утверждения, и в зелёном статусе задачи видно только одно из них.

Читать на:
Партиций меньше, чем ядер Узкое место в одном стейдже Задержка dynamic allocation
Обычный порядок причин низкой утилизации у в целом успешной задачи — иллюстративно, не измерено.

Успех задачи означает лишь то, что все таски завершились без падения. Он ничего не говорит о том, простаивала ли при этом половина ваших executor'ов.

Самая частая причина: партиций меньше, чем ядер

Если в стейдже 200 партиций, а в кластере доступно 400 ядер, половина кластера не получает ни одной задачи на всё время этого стейджа — полная стоимость, ноль работы. Это постоянно встречается на задачах, унаследовавших число shuffle-партиций от гораздо меньшего кластера и никогда не пересмотренных после масштабирования.

# грубая оценка активных слотов для стейджа active_task_slots = min(stage_partition_count, total_executor_cores)

Вторая по частоте причина: один стейдж доминирует по времени

Трансформация с тяжёлым UDF или плохо продавленным фильтром может занимать 80% всего времени выполнения задачи, затрагивая лишь малую долю партиций данных — остальной кластер простаивает, ожидая завершения этого одного стейджа. Dynamic allocation здесь помогает сократить расходы (освобождает простаивающие executor'ы), но не исправляет саму форму проблемы — задача всё равно упирается в один стейдж независимо от того, сколько executor'ов формально доступно.

Метрика, которая реально их различает

На вкладке Executors в Spark UI сравните task time каждого executor'а с общим elapsed time задачи. Соотношение заметно ниже 1 для большинства executor'ов на протяжении почти всей задачи указывает на несоответствие партиций и ядер. Соотношение около 1 для большей части задачи с явным провалом во время одного конкретного стейджа указывает на узкое место в одном стейдже — разные причины у симптома, который на дашборде расходов выглядит одинаково.

Посмотрите, как это выглядит на вашем собственном пайплайне.

Загрузите реальный event log Spark, run_results.json от dbt или экспорт метрик Flink — и получите конкретные рекомендации, которые нужно одобрить, а не ещё одно эмпирическое правило.