2017-08-28 106 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)