我正在使用带scala的Spark。我想知道单行命令是否优于单独的命令?有什么好处?它在速度方面是否获得更高的效率?为什么呢?
例如。
var d = data.filter(_(1)==user).map(f => (f(2),f(5).toInt)).groupByKey().map(f=> (f._1,f._2.count(x=>true), f._2.sum))
针对
var a = data.filter(_(1)==user)
var b = a.map(f => (f(2),f(5).toInt))
var c = b.groupByKey()
var d = c.map(f=> (f._1,f._2.count(x=>true), f._2.sum))
答案 0 :(得分:5)
两个例子之间没有性能差异;链接RDD转换或明确表示中间RDD的决定只是风格问题。 Spark的延迟评估意味着在您调用take()
或count()
之类的RDD操作之前,不会执行任何实际的分布式计算。
在执行期间,Spark将管道尽可能多的转换。对于您的示例,Spark在映射之前不会实现整个过滤数据集:filter()
和map()
转换将一起流水线化并在单个阶段执行。 groupByKey()
转换(通常)需要通过网络对数据进行混洗,因此它在单独的阶段执行。只有在filter()
d。
cache()
的输出
如果要缓存中间RDD并对其执行进一步处理,则可能需要使用第二种样式。例如,如果我想对groupByKey()
转换的输出执行多个操作,我会写类似
val grouped = data.filter(_(1)==user)
.map(f => (f(2),f(5).toInt))
.groupByKey()
.cache()
val mapped = grouped.map(f=> (f._1,f._2.count(x=>true), f._2.sum))
val counted = grouped.count()
答案 1 :(得分:0)
执行方面没有区别,但您可能需要考虑代码的可读性。我会用你的第一个例子,但是像这样:
var d = data.filter(_(1)==user)
.map(f => (f(2),f(5).toInt))
.groupByKey()
.map(f=> (f._1,f._2.count(x=>true), f._2.sum))
实际上,这更像是斯卡拉问题,而不是Spark。尽管如此,正如您可以从Spark的documentation
中显示的字数统计实现中看到的那样val file = spark.textFile("hdfs://...")
val counts = file.flatMap(line => line.split(" "))
.map(word => (word, 1))
.reduceByKey(_ + _)
counts.saveAsTextFile("hdfs://...")
你不需要担心这些事情。 Scala语言(通过懒惰等)和Spark的RDD实现处理更高抽象级别的所有内容。
如果您发现性能非常糟糕,那么您应该花时间探索原因。正如Knuth所说,“过早优化是万恶之源。”