我有一个来自s3的大型(大约85 GB压缩)gzip压缩文件,我试图用AWS EMR上的Spark处理(现在有一个m4.xlarge主实例和两个m4.10xlarge核心实例,每个都有100 GB EBS卷)。我知道gzip是一种不可拆分的文件格式,而I've seen it suggested应该重新对压缩文件进行重新分区,因为Spark最初为RDD提供了一个分区。但是,在做完
之后scala> val raw = spark.read.format("com.databricks.spark.csv").
| options(Map("delimiter" -> "\\t", "codec" -> "org.apache.hadoop.io.compress.GzipCodec")).
| load("s3://path/to/file.gz").
| repartition(sc.defaultParallelism * 3)
raw: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [_c0: string, _c1: string ... 48 more fields
scala> raw.count()
并且看一下Spark应用程序UI,我仍然看到只有一个活动执行程序(其他14个已经死了)有一个任务,并且作业永远不会完成(或者至少我没有等待足够长的时间它)。
答案 0 :(得分:6)
如果文件格式不可拆分,那么就无法避免在一个核心上完整地读取文件。为了并行化工作,您必须知道如何将工作块分配给不同的计算机。在gzip的情况下,假设您将其分成128M块。第n个块取决于第n-1个块的位置信息,知道如何解压缩,这取决于n-2-nd块,依此类推,直到第一个。
如果要并行化,则需要使此文件可拆分。一种方法是解压缩并解压缩它,或者你可以解压缩它,将它分成几个文件(每个并行任务一个文件),然后gzip每个文件。
答案 1 :(得分:0)
我遇到了这个问题,这就是解决方案。
解决此问题的最佳方法是在Spark批处理运行之前解压缩.gz文件。然后使用这个解压缩文件,之后我们可以使用Spark并行。
解压缩.gz文件的代码。
import gzip
import shutil
with open('file.txt.gz', 'rb') as f_in, gzip.open('file.txt', 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
答案 2 :(得分:0)
Spark可以并行读取单个gzip文件。
最好的方法是将其拆分成块压缩。
但是,Spark读取gzip文件的速度确实很慢。您可以这样做以加快速度:
file_names_rdd = sc.parallelize(list_of_files, 100)
lines_rdd = file_names_rdd.flatMap(lambda _: gzip.open(_).readlines())
阅读Python的两倍快于读取本地Spark gzip阅读器。