从 PySpark 中的 S3 存储桶读取数百万个小型 JSON 文件非常慢

mra*_*mah 6 amazon-s3 apache-spark apache-spark-sql pyspark databricks

我在 s3 中有一个文件夹(path = mnt/data/*.json),其中包含数百万个 json 文件(每个文件小于 10 KB)。我运行以下代码:

df = (spark.read
           .option("multiline", True)
           .option("inferSchema", False)
           .json(path))
display(df)
Run Code Online (Sandbox Code Playgroud)

问题是它非常慢。Spark 通过一个任务为此创建一个作业。该任务似乎没有更多执行程序在运行,这通常意味着作业已完成(对吗?),但由于某种原因,DataBricks 中的命令单元仍在运行。就这样卡了10分钟了。我觉得这么简单的事情应该不会超过5分钟。

Spark 作业的屏幕截图

需要考虑的注意事项:

  • 由于有数百万个 json 文件,我不能自信地说它们将具有相同的精确结构(可能存在一些差异)
  • json 文件是从相同的 REST API 中抓取的
  • 我在某处读到 inferSchema = False 可以帮助减少运行时间,这就是我使用它的原因
  • AWS s3存储桶已经安装,所以绝对不需要使用boto3

mra*_*mah 4

感谢阿南德指出“小文件问题”,我的方法非常简单。所以我的问题是我无法提取约 200 万个 json 文件,每个文件大小约 10KB。因此,我无法作为中间步骤读取它们并将其存储为镶木地板格式。我获得了一个 s3 存储桶,其中包含从网络上抓取的原始 json 文件。

无论如何,使用 python 的 zipfile 模块就派上用场了。它用于附加多个 json 文件,使每个文件至少 128MB,最多 1GB。效果很好!

还有另一种方法可以使用 AWS Glue 来完成此操作,但当然,这需要 IAM 角色授权并且可能很昂贵,但这样做的优点是您可以直接将这些文件转换为 parquet。

zip文件解决方案:https ://docs.python.org/3/library/zipfile.html

AWS Glue 解决方案:https://medium.com/searce/convert-csv-json-files-to-apache-parquet-using-aws-glue-a760d177b45f

解释小文件问题的非常好的博客文章:

https://mungingdata.com/apache-spark/compacting-files/

https://garrens.com/blog/2017/11/04/big-data-spark-and-its-small-files-problem/?unapproved=252&moderation-hash=5a657350c6169448d65209caa52d5d2c#comment-252