【发布时间】:2019-01-14 04:10:54
【问题描述】:
全部,
我们有很多离子格式的文件,我们必须在分组和过滤之前对数据进行一些计算(它们的总大小约为 1.3 TB,每个文件约为 200 - 300 MB)。 我尝试过这两种不同的方式。
首先是并行化我需要的来自 S3 的文件列表,将其转换为 RDD[Row]。然后从中创建数据框。
val rdd = ss.sparkContext.parallelize(suspendedList, suspendedList.size).flatMap(chunk => {
Ranger.consumeStreamToRow(chunk, dfSchema.value)
})
val df = ss.createDataFrame(rdd, schema)
第二种方法是并行化文件列表,并使用 AvroParquetWriter 将其写入 S3 中的 parquet 文件。将其加载为 dataFrame
val rdd = ss.sparkContext.parallelize(suspendedList, suspendedList.size).foreach( chunk => {
Ranger.writeParquetFile(chunk, avroSchema.value, TaskContext.getPartitionId())
})
第二种方式最终比第一种方式快得多,尽管它必须从 S3 进行读写。 我注意到的一件事是,与下一种方法相比,第一种方法的垃圾收集时间似乎很长,我认为这导致实际处理数据所需的时间更长。
有人可以解释第一种和第二种方法发生了什么吗?为什么即使我正在读写 S3,第二种方法最终还是要快得多? (我将执行程序内存设置为 10GB,驱动程序设置为 40GB,我使用的是 Spark EMR)
【问题讨论】:
-
您能否提供有关正在使用的
Ranger类的更多信息,因为它包含大部分逻辑。 -
当然。 Ranger.consumeStreamToRow 读取 ion 文件并将其中的数据转换为 List[Row],而 Ranger.writeParquetFile 读取 ion 文件并将其中的数据使用 GenericrecordBuilder 转换为 Record 并使用 AvroParquetWriter 将其写入 S3 文件