我正在尝试在管道中使用 Spark ML变形金刚。此管道中的一项任务是使用 join
键将传入的数据集与现有参考数据连接。
参考数据很大,但是可以在join
键上进行预分区。如果我想多次使用此转换器,而只想将参考数据加载到内存一次,我可以在转换器的生命周期中缓存参考数据吗?(可以假设参考数据是在某个地方的实木复合地板文件中
答案 0 :(得分:1)
首先,请确保您确实需要在Spark层进行缓存。读取Parquet的速度很快,联网的文件系统的速度很快,并且OS缓冲区高速缓存非常大。根据您的环境和工作集大小,您可能不需要在Spark层进行缓存(这样做甚至可能会损害性能)。
如果您确定一般来说缓存是有意义的,那么这个问题就比较棘手,因为即使有人将您已经缓存的内容传递给您,您也想做正确的事情(在这种情况下,您不需要缓存它,并且将来不希望对其进行缓存)。您可以先检查数据集是否已缓存,然后再进行缓存:
if (refdata.storageLevel == StorageLevel.NONE) refdata.cache()
以这种方式有条件地缓存参考数据非常适合在实际构建Transformer
时进行,因为cache
在访问参考数据之前不会起作用。
何时取消缓存数据是一个棘手的问题。如果某人(甚至您)已经通过了您缓存的参考数据,那么您就不会缓存它(并且您以后也不想取消缓存,以免给他们带来惊喜)。如果您跟踪是否在Transformer
中缓存了参考数据(例如,在名为uncached
的值中),那么您应该有一个必要时进行清理的方法,并在您使用时显式调用完成了。
将它们放在一起,您的变形金刚看起来像这样:
class ExampleModel(private val uncached: Boolean, private val refdata: Broadcast[DataFrame]) extends Model[Example] {
def this(df: Broadcast[DataFrame]) {
this(df.value.storageLevel == StorageLevel.NONE, df)
}
if(uncached) refdata.value.cache();
// ...
def cleanup { if (uncached) { refdata.value.uncache() } ; refdata.destroy() }
}