将tsv文件中的json列解析为Spark RDD

时间:2015-11-03 03:36:02

标签: json scala apache-spark

我正在尝试将现有的Python(PySpark)脚本移植到Scala,以提高性能。

我遇到了一些麻烦的问题 - 如何解析Scala中的json列?

这是Python版本

# Each row in file is tab separated, example:
# 2015-10-10 149775392 {"url": "http://example.com", "id": 149775392, "segments": {"completed_segments": [321, 4322, 126]}}

action_files = sc.textFile("s3://my-s3-bucket/2015/10/10/")
actions = (action_files
    .map(lambda row: json.loads(row.split('\t')[-1]))
    .filter(lambda a: a.get('url') != None and a.get('segments') != None and a.get('segments').get('completed_segments') != None)
    .map(lambda a: (action['url'], {"url": action['url'], "action_id": action["id"], "completed_segments": action["segments"]["completed_segments"],}))
    .partitionBy(100)
    .persist())

基本上,我只是试图解析json列,然后将其转换为简化版本,我可以在SparkSQL进一步处理

作为一个新的Scala用户,我发现有很多库json解析库来完成这个简单的任务。看起来stdlib中没有一个。从我到目前为止所看到的,看起来强大的键入语言使得这个简单的任务变成了一件苦差事。

我很欣赏任何正确的方向!

PS。顺便说一句,如果我遗漏了一些明显让PySpark版本爬行的东西,我很想知道它!我正在从Hadoop / MR移植一个Pig脚本,性能从17分钟下降到MR超过5个半小时!我猜它是Python的序列化开销......

1 个答案:

答案 0 :(得分:0)

如果您的目标是将数据传递给SparkSQL,并且您确定没有格式错误的字段(我的代码中没有看到任何异常处理)我根本不会手动解析:

val raw = sqlContext.read.json(action_files.flatMap(_.split("\t").takeRight(1)))

val df = raw
  .withColumn("completed_segments", $"segments.completed_segments")
  .where($"url".isNotNull && $"completed_segments".isNotNull)
  .select($"url", $"id".alias("action_id"), $"completed_segments")

关于Python代码:

  • 请勿使用!=None进行比较。一种正确的方法是使用is / is not。它在语义上是正确的(None是单身)并且明显更快。另请参阅PEP8
  • 除非必须,否则不要复制数据。发送url两次意味着更高的内存使用量和后续网络流量
  • 如果您打算使用SparkSQL检查缺失值,可以在DataFrame上执行,与Scala相同。我也会坚持DataFrame而不是RDD。

另一方面,我很怀疑序列化在这里是一个真正的问题。有一个开销,但真正的影响不应该接近你所描述的。