我试图从30个项目的列表中获取3个元素的所有可能组合的列表。我尝试使用以下代码,但它无法抛出OutOfMemoryError
。有没有比这更有效的替代方法?
val items = sqlContext.table(SOURCE_DB + "." + SOURCE_TABLE).
select("item_id").distinct.cache
val items.take(1) // Compute cache before join
val itemCombinations = items.select($"item_id".alias("id_A")).
join(
items.select($"item_id".alias("id_B")), $"id_A".lt($"id_B")).
join(
items.select($"item_id".alias("id_C")), $"id_B".lt($"id_C"))
答案 0 :(得分:3)
这种方法似乎没问题,但可能会在查询执行级别产生一些开销。假设n是一个相当小的数字,我们可以直接使用Scala实现:
val localItems = items.collect
val combinations = localItems.combinations(3)
结果是iterator
,当时可以使用一个元素,而不会产生大量的内存开销。
鉴于希望制作Spark版本,可以通过降低到RDD级别来避免查询规划器(假设存在问题)。这基本上与问题中的连接表达式相同:
val items = sqlContext.table(SOURCE_DB + "." + SOURCE_TABLE).select("item_id").rdd
val combinations = items.cartesian(items).filter{case(x,y) => x<y}.cartesian(items).filter{case ((x,y),z) => y<z}
在我的本地计算机上运行等效代码:
val data = List.fill(1000)(scala.util.Random.nextInt(999))
val rdd = sparkContext.parallelize(data)
val combinations = rdd.cartesian(rdd).filter{case(x,y) => x<y}.cartesian(rdd).filter{case ((x,y),z) => y<z}
combinations.count
// res5: Long = 165623528