上下文。我最初有一对RDD表格(id,date)的记录,我想创建一个表格的RDD(id,last_date_seen)。在原始数据中,日期是一个字符串,我使用Joda转换为DateTime
。
我已经使用combineByKey
成功完成了此操作,并且我理解groupByKey
效率低下,这在大型案例中可能不实用,但我正在尝试使用调用范围来理解方法。
我想要做的是groupByKey
然后mapValues
,获取groupByKey
生成的值列表以获取列表中的最大值。
我尝试了什么:
(我根据不同的Stack Overflow问题在DateTime上创建了一个排序,所以有一个排序。)
我尝试了很多方法,而且大多数方法都给我一个例外,即任务不可序列化。一个例子是,
rdd.groupByKey().mapValues(_.toList.sorted.last)
我已经尝试过任意数量的变体;)如果没有toList
,我会得到一个异常,即sorted不是Iterable[org.joda.time.DateTime]
的成员。我成功地使用mapValues
并做了更简单的事情,但是一旦我尝试添加排序,事情就变得糟糕了。我尝试了sortBy
并指定了Ordering
。
深入了解发送到排序方法的内容不可序列化的原因对我整体有帮助。当我陷入这个陷阱时,我不确定如何识别。
类似的Stack Overflow问题之一建议,不要使用mapValues
,而是使用sortBy
并指定它位于第二个元素上,因此.sortBy(_._2)
。Caused by: java.io.NotSerializableException:
$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$Joda$
Serialization stack:
- object not serializable (class:
$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$Joda$,
value: $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$Joda$@6fc2db37)
- field (class: $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC,
name: Joda$module, type: class $iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$$iwC$Joda$)
。这对我来说也失败了。理想情况下,如果这样做是有意义的,我也想知道这一点。
这似乎是一件非常简单且可能很常见的事情,所以我觉得我错过了一些东西。
编辑 - 添加了异常的更多细节。请注意,我无法重现此错误。
错误堆栈中的不可序列化错误表明我在另一个Stack Overflow中找到的隐式排序是罪魁祸首。请注意,我无法重现这个让我困扰数小时的错误(请参阅答案)。
object Joda {
implicit def dateTimeOrdering: Ordering[DateTime] =
Ordering.fromLessThan(_ isBefore _)
}
之前已经定义了Joda模块。
{{1}}
答案 0 :(得分:0)
我原来的问题确实有两个组成部分: *如何使用groupBy转换RDD以检索每个id的最后一次看到的日期,以及 *为什么我试图给出“任务不可序列化”错误的方法。
不幸的是,在重新启动spark-shell并回溯我的步骤后,我无法重现此错误。我在问题中列出的代码与我已经建立的DateTime顺序配对工作正常。我最近有另一个这样的问题,我能够将它追溯到隐式值中的冲突,我之前在shell中设置了完全不同的目的。我怀疑这也是罪魁祸首,但无法证实这一点。
评论中引用的另一个Stack Overflow问题表明Joda已经为其他人带来了问题。
为了完整性,我能够进行转换并提取几种方式的最后日期。 @ zero323在使用reduceByKey的评论中给出的最简单的方法。
使用groupByKey,问题中的代码
rdd.groupByKey().mapValues(_.toList.sorted.last)
当下面的隐式排序到位时,工作正常:
object Joda {
implicit def dateTimeOrdering: Ordering[DateTime] =
Ordering.fromLessThan(_ isBefore _)}
import Joda._
同样,
rdd.groupByKey.mapValues(_.toList.max)
结果相同。
我还使用定义的顺序复制结果并将其传递给显式排序。
不幸的是,我无法确定为什么对象Joda在第一个会话中抛出异常而在接下来的很多次尝试中没有。