我有这个程序,它使用Apache Spark来计算单词的频率。
我用键/值对(word =键,frequency = value)创建一个RDD。数据集分布在工作程序节点上。函数频繁单词计数以固定的时间间隔执行。它从文件中选择字符串。 然后将其转换为键值对,并连接到wordDataset-RDD。计数频率> 50的单词。
有人告诉我这种方法无效。有人可以告诉我为什么以及如何改善它吗?
val sc = new SparkContext(...)
var wordDataset:RDD[(String, Int)] = sc.sequenceFile[String, Int](“…”).persist()
def frequentWordCount(fileName:String):Long = {
val words = sc.sequenceFile[String](fileName)
val joined = wordDataset.join(words.map(x=>(x,1)))
joined.filter(x=>x._1._2>50).count
}
答案 0 :(得分:0)
您大约有多少个常用词?对于许多合理的任务,我认为它应该意外地小-足够小以适合每台机器的内存。在IIRC中,单词倾向于服从幂律分布,因此不应有那么多“通用”单词。在那种情况下,广播一组常用词可能比加入要快得多:
val sc = new SparkContext(...)
var commonWords: BroadCast[Set[String]] = sc.broadcast(sc.sequenceFile[String, Int](“…”).filter(_._2 > 50).collect().toSet)
def frequentWordCount(fileName:String):Long = {
val words = sc.sequenceFile[String](fileName)
words.filter(commonWords.value.contains).count
}
如果您多次调用frequentWordCount
,则最好只执行一次RDD操作,将您的单词与文件名关联起来,然后进行分组和计数等等。具体取决于如何用过的。
答案 1 :(得分:0)
如果常用单词的数量足够小以适合内存Set
,则其他答案表明(除非,您需要map(_._1)
之后filter
在内存中 sc.sequenceFile[String](fileName)
.keyBy(identity)
.join(wordDataset.filter(_._2 > 50))
.count
。
否则,您可以改进的两件事是(1)在加入连接之前过滤 ,您希望尽快抛出多余的数据,而不是不必要地对其进行多次扫描,以及(2 ),通常来说,您总是希望将较大的数据集连接到较小的数据集,而不是相反。
Array
(
[0] => Teacher Object
(
[subject:Teacher:private] => Matematicas
[teacherType:Teacher:private] => Master
[teachers:Teacher:private] => Array
(
[0] => Teacher Object
(
[subject:Teacher:private] => Matematicas 2
[teacherType:Teacher:private] => Senior
[teachers:Teacher:private] => Array
(
[0] => Teacher Object
(
[subject:Teacher:private] => Ciancias 1
[teacherType:Teacher:private] => Junior
[teachers:Teacher:private] => Array
(
)
[id:Person:private] => 7
[name:Person:private] => Pedro
[nickname:Person:private] => PedroBoy
)
)