我是Spark和Scala的新手。我正在阅读Spark的distinct()函数。但是我找不到任何适当的细节。我有一些我无法解决的疑问,并将其写下来。
如何在Spark中实现distinct()?
我对Spark源代码不太了解,无法识别整个流程。 当我检查执行计划时,只能看到ShuffleRDD
不同的时间复杂度是多少?
我还从Google搜索中发现它也以某种方式使用哈希和排序。
所以,我想它是否使用与在Hashset的帮助下从数组中获取唯一元素相同的原理。 如果是一个系统,我会猜到时间复杂度为O(nlogn)。
但是它分布在许多分区中并混洗了,时间复杂度是多少?
在特定情况下是否有避免混洗的方法?
如果我确保根据用例正确划分数据, 我可以避免改组吗?
即例如,假设将数据帧中具有唯一行的ArrayType列爆炸会创建新行,而其他列会重复。 我将选择其他列。 这样,我确保每个分区的重复项都是唯一的。 由于我知道每个分区的重复项都是唯一的, 我可以避免随机播放,而只需将副本重复地放在该分区中
我也找到了这个Does spark's distinct() function shuffle only the distinct tuples from each partition。
感谢您的帮助。 如果我在任何地方错了,请纠正我。
答案 0 :(得分:3)
如何在Spark中实现distinct()?
通过应用具有None
值的虚拟聚合。大概
rdd.map((_, None)).reduceByKey((a, b) => a)
不同的时间复杂度是多少?
鉴于该过程的整体复杂性,很难估计。它至少应为O(N log N),因为shuffle需要排序,但是考虑到需要构建多个额外的核心数据结构(包括关联数组)所需的其他多个操作,则对数据进行序列化/反序列化的操作可能会更高,并且实际上由IO主导操作,而不是单纯的算法复杂性。
在特定情况下是否有避免混洗的方法?
是的,如果保证将潜在的重复项放在同一分区上,
您可以使用mapPartitions
对数据进行重复数据删除,尤其是在数据经过排序或以其他方式保证在孤立的邻域中有重复项的情况下。否则,除非您接受概率过滤器(例如Bloom过滤器)的近似结果,否则您可能会受到内存要求的限制。
尽管通常这是不可能的,但是这样的操作将是非本地的。