2017-08-28 95 views
1

我有一个csv文件:(customerId,orderId,花费)。我计算使用两种方法每一位客户的总支出:DataBrame with groupBy与RDD with reduceByKey

方法1:使用数据帧和GROUPBY

val df = ss.read 
.option("header", false) 
.option("inferSchema", true) 
.csv("data.csv") 

df 
.groupBy("_c0") 
.sum("_c2") 
.collect() 

方法2:采用RDD和reduceByKey

sc 
.textFile("data.csv") 
.map(parseLine) 
.reduceByKey(_ + _) 
.collect() 

private def parseLine(line: String) = { 
    val fields = line.split(",") 
    (fields(0).toInt, fields(2).toFloat) 
} 

结果这两种方法是相同的。然而,方法2总是比方法1更快(2倍)。

第一个问题:是因为方法1使用了groupBy?如果是这样,当我在笔记本电脑上运行时会发生什么。即只有1个节点,即没有洗牌成本?

这是我的火花会话配置

.master("local[*]") 

第二个问题:我怎么能修改方法1使用数据帧,同时保留类似的方法2出色的表现?

谢谢!

+0

我已阅读。但这里的重点是我想使用DataFrame,而不是RDD,因为提到的DataFrame文档具有更好的性能。此外,输入文件已经结构化的数据,这是有道理的使用数据帧/数据集,我是不是正确的? –

回答

0

你的第一个代码扫描数据进行两次:

  • 一旦到inferchema
  • 一次执行计数。

没有任何进一步的信息我会把执行速度慢归因于这个事实。还有其他的不同之处,比如计算执行计划的成本。

特定内存配置(包括堆外存储器的大小)可能会进一步影响性能。

我怎么能修改方法1使用数据帧,同时保留类似的方法2出色的表现?

read方法提供模式参数。

当我在笔记本电脑上运行时,它会发生什么?即只有1个节点,即没有洗牌成本?

由于本地通信,本地机上的洗牌成本可能会降低,但它仍然是一个完整的洗牌,包括磁盘IO,并且它仍然很昂贵。

这是因为方法1是使用GROUPBY

groupBy无关吧。 Dataset.groupBy不是RDD.groupBy(Key)