在Spark中有效地聚合许多CSV

时间:2015-08-03 20:01:05

标签: csv amazon-s3 apache-spark sparkr

原谅我的简单问题,但我对Spark / Hadoop相对较新。

我正在尝试将一堆小的CSV文件加载到Apache Spark中。它们目前存储在S3中,但如果能简化,我可以在本地下载它们。我的目标是尽可能高效地完成这项工作。看起来让我的数十名Spark工作人员无所事事地让一些单线程主人下载并解析一堆CSV文件会很遗憾。我希望有一种惯用的方式来分发这项工作。

CSV文件的排列方式如下:

2014/01-01/fileabcd.csv
2014/01-01/filedefg.csv
...

我有两年的数据,每天都有目录,每个目录中都有几百个CSV。所有这些CSV应该具有相同的模式,但是当然可能一个CSV出错并且如果存在一些有问题的文件,我讨厌整个作业崩溃。只要我在某个日志中通知我发生了这些文件,就可以跳过这些文件。

似乎我想到的每个Spark项目都采用相同的形式,我不知道如何解决它。 (例如,尝试读取一堆制表符分隔的weather data,或者阅读一堆日志文件来查看这些。)

我尝试过什么

我已经尝试过SparkR和Scala库。我真的不在乎我需要使用哪种语言;我对使用正确的习语/工具更感兴趣。

Pure Scala

我最初的想法是枚举parallelize所有year/mm-dd组合的列表,以便我可以让我的Spark工作人员每天独立处理(下载并解析所有CSV文件,然后将它们堆叠起来)彼此顶部(unionAll())以减少它们)。遗憾的是,使用spark-csv库下载和解析CSV文件只能在“父”/主作业中完成,而不能作为Spark doesn't allow job nesting从每个子项中完成。所以只要我想使用Spark库进行导入/解析,这将无法工作。

混合语言

当然,您可以使用语言的本机CSV解析来读取每个文件,然后将它们“上传”到Spark。在R中,这是一个包的组合,用于从S3获取文件,然后是read.csv,最后用createDataFrame()将数据导入Spark。不幸的是,这真的很慢,而且似乎也是我希望Spark工作的方式。如果我的所有数据都是通过R管道才可以进入Spark,为什么还要使用Spark呢?

Hive / Sqoop / Phoenix / Pig / Flume / Flume Ng / s3distcp

我开始研究这些量身定制的工具,很快就不堪重负。我的理解是,可以使用许多/所有这些工具将我的CSV文件从S3转换为HDFS。

当然,从HDFS读取我的CSV文件比S3更快,因此解决了部分问题。但我仍然需要解析成千上万的CSV,并且不知道在Spark中使用分布式方法。

2 个答案:

答案 0 :(得分:1)

现在(Spark 1.4)SparkR支持jsonparquet文件结构。可以解析Csv文件,但是需要使用额外的jar启动spark上下文(需要将其下载并放置在相应的文件夹中,我自己从未这样做,但我的同事们已经这样做了)。

sc <- sparkR.init(sparkPackages="com.databricks:spark-csv_2.11:1.0.3")
sqlContext <- sparkRSQL.init(sc)

the docs中有更多信息。我希望更新的火花释放可以为此提供更多支持。

如果您不这样做,则需要使用不同的文件结构或使用python将所有文件从.csv转换为.parquet。这是最近一次python演讲的片段。

data = sc.textFile(s3_paths, 1200).cache()

def caster(x):
    return Row(colname1 = x[0], colname2 = x[1])

df_rdd = data\
    .map(lambda x: x.split(','))\
    .map(caster)

ddf = sqlContext.inferSchema(df_rdd).cache()

ddf.write.save('s3n://<bucket>/<filename>.parquet')

另外,您的数据集有多大?你可能甚至不需要火花进行分析。请注意,目前也是如此;

  • SparkR只支持DataFrame。
  • 还没有分布式机器学习。
  • 对于可视化,如果要使用ggplot2等库,则需要将分布式数据帧转换回正常数据帧。
  • 如果你的数据集不超过几千兆字节,那么学习火花的额外麻烦可能就不值得了
  • 现在它很谦虚,但未来可以期待更多

答案 1 :(得分:1)

我之前遇到过这个问题(但是读了很多Parquet文件)我的建议是避免使用数据帧并使用RDD。

使用的一般习语是:

  1. 读入每个文件为一行的文件列表(在驱动程序中)。这里的预期输出是字符串列表
  2. 并行化字符串列表并使用客户csv阅读器映射它们。返回是一个案例类列表。
  3. 如果您希望像List [weather_data]这样的数据结构可以重写为镶木地板或数据库,那么您也可以使用flatMap。