Эта проблема возникла из-за фундаментальной проблемы с DirectFileOutputCommitter
, который использовался здесь по умолчанию.
Здесь есть две вещи: OOM исполнителя и затем FileAlreadyExistsException
при повторных попытках, вызывающих повторные попытки (и, следовательно, запрос SQL) не удастся.
Причина: DirectFileOutputCommitter
попытается записать выходные файлы в одной попытке задачи в конечный выходной путь. Он сделает это, записав в промежуточный каталог, а затем переименовав его в окончательный путь и удалив оригинал. Это плохо и подвержено несоответствиям и ошибкам, а также не рекомендуется Spark.
Вместо этого я использовал коммиттер Netflix S3 , который делал бы это в многочастной манере. Сначала он запишет файлы на локальный диск, затем во время фиксации задачи каждый из них будет загружен в S3 по частям, но не будет сразу виден, затем во время фиксации задания (что произойдет только тогда, когда все задачи будут выполнены. успешно, так что это безопасная операция) данные локального диска будут удалены и загрузка будет завершена (теперь данные будут видны на S3). Это предотвращает неудачные задачи, напрямую записывающие данные в S3, и, следовательно, избегает FileAlreadyExistsException
при повторной попытке.
Теперь для OOM исполнителя - они все еще выполняются для моего запроса, но повторные попытки успешны, которые также терпели неудачу ранее с DirectFileOutputCommitter
.
Чтобы решить эту проблему, я в основном сделал
set spark.sql.sources.outputCommitterClass=com.netflix.s3.S3DirectoryOutputCommitter;