Infra

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

Память driver'а против памяти executor'а: это не одна и та же задача по настройке

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

Читать на:
collect() / toPandas() Слишком большой broadcast Слишком много партиций
Обычные источники давления на память driver'а, примерно по порядку — иллюстративно, не измерено.

Driver выполняет принципиально другую работу, чем executor: он строит и планирует DAG, а не обрабатывает партиции данных — а значит, давление на его память возникает из совершенно других мест.

Что на самом деле выполняется на driver'е

Построение плана и планирование DAG, координация назначения задач executor'ам, сбор значений аккумуляторов и всё, что явно возвращает данные обратно в процесс driver'а — collect(), toPandas(), take() для большого результата. Ничто из этого не является «обработкой партиций вашего датасета» — это целиком работа executor'ов.

Почему у OOM драйвера другие реальные причины

Самая частая, безусловно: кто-то вызвал .collect() или .toPandas() на DataFrame, оказавшемся гораздо больше ожидаемого, стянув всё целиком в память единственного процесса driver'а вместо того, чтобы оставить данные распределёнными. На втором месте: broadcast join (см. статью о broadcast join), где «маленькая» сторона на деле маленькой не оказалась — driver собирает эти данные прежде, чем передать их executor'ам, так что падает по OOM первым. На третьем: задача, отслеживающая огромное число партиций или очень глубокий DAG, где сами накладные расходы на планирование — без каких-либо реальных данных — съедают heap driver'а.

Почему увеличение памяти executor'а тут не поможет

spark.executor.memory и spark.driver.memory — действительно раздельные настройки, управляющие раздельными JVM-процессами: увеличение одной никак не влияет на давление на другую. OOM драйвера из-за неожиданного collect() требует либо исправления кода (агрегировать перед сбором, или не собирать вовсе), либо конкретно spark.driver.memory; добавление памяти executor'у в этом случае адресует процесс, который никогда и не был тем, у кого кончалась память.

Быстрая диагностика: OOM executor'а проявляется как падение конкретной задачи с ExecutorLostFailure или похожим сообщением в event log. OOM драйвера убивает всё приложение целиком, часто без единой конкретной упавшей задачи — совершенно другая картина, и первая подсказка, что вы смотрите не на ту настройку.

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

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