Медленный или неполный saveAsParquetFile от EMR Spark до S3
У меня есть кусок кода, который создает DataFrame
и сохраняет его на S3. Ниже создает DataFrame
из 1000 строк и 100 столбцов, заполненных math.Random
, Я запускаю это на кластере с 4 х r3.8xlarge
рабочие узлы и настройка большого количества памяти. Я пробовал с максимальным количеством исполнителей и по одному исполнителю на узел.
// create some random data for performance and scalability testing
val df = sqlContext.range(0,1000).map(x =>
Row.fromSeq((1 to 100).map(y => math.Random)))
df.saveAsParquetFile("s3://kirk/my_file.parquet")
Моя проблема в том, что я могу создать гораздо больше DataFrame
в памяти, чем я могу сохранить в S3.
Например, 1 миллиард строк и 1000 столбцов могут быть построены и запрошены, но 100 миллионов строк и 100 столбцов завершаются сбоем, когда я пишу в S3 таким способом. Я не получаю хороших сообщений из контекста Spark, но работа не удастся, потому что слишком много задач не удалось.
Есть ли какая-нибудь конфигурация для более эффективного сохранения файла? Должен ли я настроить Spark по-другому, чтобы saveAsParquetFile
?
Это трассировка стека от исполнителя:
15/09/09 18:10:26 ERROR sources.InsertIntoHadoopFsRelation: Aborting task.
java.lang.OutOfMemoryError: Java heap space
at parquet.column.values.dictionary.IntList.initSlab(IntList.java:87)
at parquet.column.values.dictionary.IntList.<init>(IntList.java:83)
at parquet.column.values.dictionary.DictionaryValuesWriter.<init>(DictionaryValuesWriter.java:85)
at parquet.column.values.dictionary.DictionaryValuesWriter$PlainIntegerDictionaryValuesWriter.<init>(DictionaryValuesWriter.java:549)
at parquet.column.ParquetProperties.getValuesWriter(ParquetProperties.java:88)
at parquet.column.impl.ColumnWriterImpl.<init>(ColumnWriterImpl.java:74)
at parquet.column.impl.ColumnWriteStoreImpl.newMemColumn(ColumnWriteStoreImpl.java:68)
at parquet.column.impl.ColumnWriteStoreImpl.getColumnWriter(ColumnWriteStoreImpl.java:56)
at parquet.io.MessageColumnIO$MessageColumnIORecordConsumer.<init>(MessageColumnIO.java:178)
at parquet.io.MessageColumnIO.getRecordWriter(MessageColumnIO.java:369)
at parquet.hadoop.InternalParquetRecordWriter.initStore(InternalParquetRecordWriter.java:108)
at parquet.hadoop.InternalParquetRecordWriter.<init>(InternalParquetRecordWriter.java:94)
at parquet.hadoop.ParquetRecordWriter.<init>(ParquetRecordWriter.java:64)
at parquet.hadoop.ParquetOutputFormat.getRecordWriter(ParquetOutputFormat.java:282)
at parquet.hadoop.ParquetOutputFormat.getRecordWriter(ParquetOutputFormat.java:252)
at org.apache.spark.sql.parquet.ParquetOutputWriter.<init>(newParquet.scala:83)
at org.apache.spark.sql.parquet.ParquetRelation2$$anon$4.newInstance(newParquet.scala:229)
at org.apache.spark.sql.sources.DefaultWriterContainer.initWriters(commands.scala:470)
at org.apache.spark.sql.sources.BaseWriterContainer.executorSideSetup(commands.scala:360)
at org.apache.spark.sql.sources.InsertIntoHadoopFsRelation.org$apache$spark$sql$sources$InsertIntoHadoopFsRelation$$writeRows$1(commands.scala:172)
at org.apache.spark.sql.sources.InsertIntoHadoopFsRelation$$anonfun$insert$1.apply(commands.scala:160)
at org.apache.spark.sql.sources.InsertIntoHadoopFsRelation$$anonfun$insert$1.apply(commands.scala:160)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:63)
at org.apache.spark.scheduler.Task.run(Task.scala:70)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:213)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
1 ответ
Я думаю, что вам нужно перераспределить ваш фрейм данных (у вас должно быть как минимум numberOfWorkerInstances * numberOfCoresOnEachInstance количество разделов), чтобы позволить параллельную запись в S3.