Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala spark数据集的正确单元平面映射操作?_Scala_Apache Spark - Fatal编程技术网

Scala spark数据集的正确单元平面映射操作?

Scala spark数据集的正确单元平面映射操作?,scala,apache-spark,Scala,Apache Spark,我正在寻找具有以下签名的函数: bind[A, B](f: A => Dataset[B], ds: Dataset[A]): Dataset[A] 火花图书馆里有这样的东西吗?(flatMap不幸地需要从a到TraversableOnce[B]的映射,这意味着我必须具体化我的数据集,除非我遗漏了什么)。 如果没有,我们将如何实现这样的功能?RDD不是monad。 RDD对象仅在驱动程序上有意义,而map/flatmap功能在工人上执行。因此,在map/flatmap操作中不能发出RDD

我正在寻找具有以下签名的函数:

bind[A, B](f: A => Dataset[B], ds: Dataset[A]): Dataset[A]
火花图书馆里有这样的东西吗?(
flatMap
不幸地需要从
a
TraversableOnce[B]
的映射,这意味着我必须具体化我的数据集,除非我遗漏了什么)。
如果没有,我们将如何实现这样的功能?

RDD
不是monad。
RDD
对象仅在驱动程序上有意义,而
map/flatmap
功能在工人上执行。因此,在map/flatmap操作中不能发出
RDD
s


Dataset
RDD
的门面,所以我想这也是不可能的。

假设您有
N个
节点,每个节点上都有
M
内存。
此外,假设
f(a)
对于所有
a数据集[B])
的大小大致相同:在每次调用此类
flatMap

时都必须做出非平凡的设计决策
a=>transversableOnce[B]应该做什么
在不将数据集具体化为TraveTableOnce的情况下,还不能进行映射。我认为它无法正常工作,因为Spark通常不支持在RDD操作中调用/创建RDD。在Spark执行模型下,
rdd.map(element=>otherRDD.whatever)
的任何味道都没有意义(尽管它“在概念上”是有意义的)。RDD不是集合(当然,从鸟瞰的角度看,它们看起来是这样的,这样很容易理解它们的本质),它们是分布式计算的一个变体。
def flatMap[U](func:(T)⇒ TraversableOnce[U])
的定义是这样的,因为您实际上是在处理
数据集[T]
的一个子集,而不是整个数据集。正如其他人所说,这是因为Spark对数据进行了内部分区,这样每个工作人员都可以得到一块数据。因此,返回
数据集[B]
是没有意义的,因为我们只对子集进行操作<代码>数据集[A]不遵守单子定律,因此它不是单子。@Gal是的,它是一个设计“细节”。但这是一个非常重要的问题,你不能轻易改变它。但事实上,分布式数据集不能是一元数据集并没有数学上的原因。我的意思是,从技术上讲,您可以发出一个
RDD
(或
dataset
),因为您可以将
Seq
转换为
dataset
,但这需要生成一个具体的序列来开始。虽然,我不确定
数据集是否有
编码器,因此可能无法编译…@Gal您可以在什么样的上下文中将
Seq
转换为
数据集
?工作节点上没有spark上下文。@您不能。理论上可以(它将编译),但它在Spark执行模型中无效,通常会在运行时失败或死锁。这里要考虑的不仅仅是一些类型。在函数编程的可组合性方面,您可能会失去一些“类型纯度”。但这种限制是有道理的。驱动程序可以创建任意大的集合,并作为数据集轻松地访问它们。工作人员必须在自己的内存空间内工作,而且永远不会超出内存空间:他们不应该创建数据集(其他任意大的“集合”)。我不确定我是否遵守了<代码>绑定(f,ds)
几乎没有内存消耗,因为没有收集任何内容。它不需要比
map
filter
flatMap
更多的内存
f
是一个创建未收集的
Dataset
对象的函数(否则它就不是
Dataset
)。另外,如果我错了,请纠正我,但我不明白为什么N*m应该大于任何值。如果需要,@Gal“
bind(f,ds)
几乎没有内存消耗”看起来有点像是对由
map
s和
filter
s组成的延迟计算执行计划的引用。但一旦您强制spark对所有内容进行评估并将其缓存在RAM中,那么它肯定会占用大量内存。我不确定它如何“迭代地工作”?它应该从内存中取出数据集的一部分并一直重新计算它们吗?好吧,如果它应该这样做,那么你必须通过显式地编码它来承担责任。我不确定这是否是一种直观的默认行为?它确实是对延迟评估执行计划的引用,这就是我返回延迟评估
数据集的原因。理想情况下,spark最终将评估
数据集[B]
,并将其视为任何其他
数据集
。在绑定操作中创建数据集不需要比创建任何其他
数据集
占用任何额外内存,这通常是在单个驱动程序上本地完成的(假设我的术语正确)。至于内存:我想这取决于您正在进行的收集类型。如果它能够以这样一种方式对数据进行分区,即不是所有数据都必须同时保存在(分布式)内存中,那么我看不出有什么问题。
|f(a)| >= M .
N * M >= ds.size * |f(a)| >= ds.size * M
N >= ds.size
def bind[A, B](f: A => Dataset[B], ds: Dataset[A]): Dataset[A] = {
  ds.collect.map(f).reduce(_ union _)
}