如何改进我的spark应用程序的reducebykey部分?

时间:2016-05-27 07:17:59

标签: python apache-spark cassandra datastax datastax-enterprise

我有64个火花核心。我的cassandra集群中有超过8000万行数据,相当于4.2 GB。我现在需要82秒来处理这些数据。我希望这减少到8秒。有什么想法吗?这甚至可能吗?感谢。

这是我想改进的火花应用程序的一部分:

axes = sqlContext.read.format("org.apache.spark.sql.cassandra")\
    .options(table="axes", keyspace=source, numPartitions="192").load()\
    .repartition(64*3)\
    .reduceByKey(lambda x,y:x+y,52)\
    .map(lambda x:(x.article,[Row(article=x.article,at=x.at,comments=x.comments,likes=x.likes,reads=x.reads,shares=x.shares)]))\
    .map(lambda x:(x[0],sorted(x[1],key=lambda y:y.at,reverse = False))) \
    .filter(lambda x:len(x[1])>=2) \
    .map(lambda x:x[1][-1])

修改

这是我目前运行的代码,上面发布的代码是一个抱歉混淆的实验。上面的问题与此代码有关。

axes = sqlContext.read.format("org.apache.spark.sql.cassandra").options(table="axes", keyspace=source).load().repartition(64*3) \
                    .map(lambda x:(x.article,[Row(article=x.article,at=x.at,comments=x.comments,likes=x.likes,reads=x.reads,shares=x.shares)])).reduceByKey(lambda x,y:x+y)\
                    .map(lambda x:(x[0],sorted(x[1],key=lambda y:y.at,reverse = False))) \
                    .filter(lambda x:len(x[1])>=2) \
                    .map(lambda x:x[1][-1])

由于

1 个答案:

答案 0 :(得分:2)

<强>问题

为什么此代码无法正常工作,假设未经修改的Spark分发

步骤一步:

  1. 这两行应该创建一个Spark DataFrame。到目前为止一切顺利:

    sqlContext.read.format("org.apache.spark.sql.cassandra")
      .options(table="axes", keyspace=source, numPartitions="192").load()
    

    唯一可能的问题是numPartitions,据我记忆,这不是公认的选择。

  2. 这几乎是一个垃圾代码。在没有做任何实际工作的情况下改组数据不太可能让你随处可见。

    .repartition(64*3)
    
  3. 此时切换到RDD。由于Row实际上是tuple的子类,而reduceByKey可能仅适用于pairwise RDDs,因此每个元素都必须是大小为2的元组。我不确定为什么选择52分区虽然。

    .reduceByKey(lambda x,y:x+y,52)
    
  4. 由于reduceByKey总是导致大小为2的元组的RDD,因此部分根本不应该

    .map(lambda x: (x.article,[Row(article=x.article,at=x.at,comments=x.comments,likes=x.likes,reads=x.reads,shares=x.shares)]))\
    

    特别是x不能包含articlecomments等属性。而且这段代码

    [Row(article=x.article,at=x.at,comments=x.comments,likes=x.likes,reads=x.reads,shares=x.shares)] 
    

    创建大小为1的list(见下文)。

    以下部分

    Row(article=x.article, ...)
    

    因为另外一个原因而闻起来很腥。如果存在一些过时的列,则应在将数据转换为RDD之前将其过滤掉,以避免过多的流量并减少内存使用量。如果没有过时的列,则没有理由通过创建新对象对Python GC施加更多压力。

  5. 由于x[1]只有一个元素排序,因此没有意义:

    .map(lambda x:(x[0],sorted(x[1],key=lambda y:y.at,reverse = False))) \
    
  6. 此过滤器应始终返回空的RDD

    .filter(lambda x:len(x[1])>=2) \
    
  7. 这并没有执行任何有用的操作:

    .map(lambda x:x[1][-1])
    
  8. <强>摘要

    如果您使用此代码的某些版本,则问题中显示的订单很可能会混淆并从第4点开始映射:

    .map(lambda x: (x.article,[Row(....)]))
    

    reduceByKey之前:

    .reduceByKey(lambda x,y:x+y,52)
    

    如果是这样的话,那么你实际上使用的.reduceByKey to perform groupByKey等同于groupByKey及其所有问题(Python)或效率较低(Scala)。此外,它会减少高度可疑的分区数量。

    如果那是真的there is no good reason to move data out of JVMDataFrame - &gt; RDD转换),并且相应的序列化 - 反序列化,即使有,也可以通过{{ 1}}不是按键分组。

    max

    相关问题: