通过Spark EMR读取嵌套目录中的S3文件

时间:2017-06-28 13:49:55

标签: amazon-web-services apache-spark amazon-s3 pyspark emr

我想出了如何从S3目录中将文件读入我的pyspark shell(和脚本),例如:使用:

rdd = sc.wholeTextFiles('s3n://bucketname/dir/*')

但是,尽管让我读取ONE目录中的所有文件非常棒,但我想从所有目录中读取每个文件。

我不想让它们变平或立刻加载所有内容,因为我会遇到内存问题。

相反,我需要它以批量方式自动加载每个子目录中的所有文件。这可能吗?

这是我的目录结构:

S3_bucket_name - >年(2016年或2017年) - >月(最多12个文件夹) - >一天(最多31个文件夹) - >子日文件夹(最多30个;基本上只是每天分区收集)。

这样的事情,除了它将会持续12个月甚至31天......

BucketName
|
|
|---Year(2016)
|       |
|       |---Month(11)
|       |      |
|       |      |---Day(01)
|       |      |      |
|       |      |      |---Sub-folder(01)
|       |      |      |
|       |      |      |---Sub-folder(02)
|       |      |      |
|       |      |---Day(02)
|       |      |      |
|       |      |      |---Sub-folder(01)
|       |      |      |
|       |      |      |---Sub-folder(02)
|       |      |      |
|       |---Month(12)
|
|---Year(2017)
|       |
|       |---Month(1)
|       |      |
|       |      |---Day(01)
|       |      |      |
|       |      |      |---Sub-folder(01)
|       |      |      |
|       |      |      |---Sub-folder(02)
|       |      |      |
|       |      |---Day(02)
|       |      |      |
|       |      |      |---Sub-folder(01)
|       |      |      |
|       |      |      |---Sub-folder(02)
|       |      |      |
|       |---Month(2)

上面的每个箭头代表一个分叉。例如我已经收集了2年的数据,因此在"年"叉子。然后每年最多12个月,然后每个月最多31个可能的日期文件夹。在每一天,最多会有30个文件夹,因为我将它分开......

我希望这是有道理的......

我正在查看另一篇文章(read files recursively from sub directories with spark from s3 or local filesystem),我相信他们建议使用通配符,所以类似于:

rdd = sc.wholeTextFiles('s3n://bucketname/*/data/*/*') 

但问题是它试图在各个子目录中找到一个公共文件夹 - 在这种情况下没有保证,我只需要一切。

然而,在那条推理线上,我想如果我做了......:

rdd = sc.wholeTextFiles("s3n://bucketname/*/*/*/*/*')

但问题是,现在我收到OutOfMemory错误,可能是因为它一次性加载所有内容并且吓坏了。

理想情况下,我能做的就是:

转到当天的子目录级别并阅读其中的内容,例如

首先阅读2016/12/01,然后2016/12/02,直至2012/12/31,然后是2017/01/01,然后是2017/01 / 02,... 2017/01/31等等。

这样,我不会像上面那样使用五个通配符(*),而是以某种方式让它知道通过" day"的每个子目录。

我想过使用python字典来指定每天的文件路径,但这似乎是一种相当麻烦的方法。我的意思如下:

file_dict = { 
    0:'2016/12/01/*/*', 
    1:'2016/12/02/*/*', 
    ...
    30:'2016/12/31/*/*',
}

基本上用于所有文件夹,然后迭代它们并使用以下内容加载它们:

sc.wholeTextFiles('s3n://bucketname/' + file_dict[i])

但我不想手动输入所有这些路径。我希望这是有道理的......

编辑:

提出问题的另一种方法是,如何以批处理方式从嵌套的子目录结构中读取文件?如何在python中的s3存储桶中枚举所有可能的文件夹名称?也许这会有所帮助......

EDIT2:

我的每个文件中的数据结构如下:

{json object 1},
{json object 2},
{json object 3},
...
{json object n},

因为它是"真正的json",它或者只需要像上面那样在最后没有尾随逗号或类似的东西(注意方括号,并且缺少最后的尾随逗号) :

[
   {json object 1},
   {json object 2},
   {json object 3},
   ...
   {json object n}
 ]

我之所以在PySpark中完成它作为我提交的脚本是因为我强迫自己手动处理这种格式化的怪癖。如果我使用Hive / Athena,我不知道如何处理它。

1 个答案:

答案 0 :(得分:1)

为什么不使用Hive,甚至更好,Athena?这些将在文件系统的顶部部署表,以便您访问所有数据。然后你可以把它捕获到Spark

或者,我相信您也可以在Spark中使用HiveQL来设置文件系统位置的tempTable ontop,并将其全部注册为Hive您可以执行SQL的表格。我已经做了一段时间了,但它绝对可行