2017-04-26 67 views
1

我想了解Spark如何分区数据。假设我有一个像图中那样的执行DAG(橙色框是舞台)。如果RDD没有被分区,则两个groupByjoin操作应该是非常沉重的。了解Spark分区

enter image description here 那么明智的做法是使用.partitonBy(new HashPartitioner(properValue))来P1,P2,P3和P4避免洗牌?分区现有RDD的成本是多少?何时不适合划分现有的RDD?如果我没有指定分区程序,Spark不会自动分区我的数据吗?

谢谢

回答

5

tl; dr分别回答您的问题:如果可以的话,最好先进行分区;可能比不分区;无论如何,你的RDD都是以这样或那样的方式分区的;是。

这是一个相当广泛的问题。它占据了我们课程的很大一部分!但是,我们尽量在不写小说的情况下尽可能多地处理分区问题。

如您所知,使用类似Spark这样的工具的主要原因是因为您有太多的数据需要在一台机器上进行分析,而没有将风扇看作喷气发动机。数据分布在集群中所有机器上的所有核心中,所以是的,根据数据,存在默认分区。请记住,数据已经静态分发(在HDFS,HBase等中),因此Spark默认根据默认策略进行分区,以将数据保留在已存在的机器上 - 默认分区数量相同到群集上的核心数量。您可以通过配置spark.default.parallelism来覆盖此默认编号,并且您希望此编号为每台机器每个核心2-3个。

但是,为了您的分析和目的,通常希望属于一组的数据(例如,具有相同密钥的数据,其中HashPartitioner将应用)位于同一分区中,而不管它们从何处开始。以尽量减少后来的洗牌。 Spark还提供RangePartitioner,或者您可以很容易地根据自己的需求推出自己的产品。但是你是对的,从默认分区到自定义分区有一个前期洗牌成本;它几乎总是值得的。

一开始进行分区通常是明智的(而不是延迟不可避免的与partitionBy),然后repartition(如果稍后需要的话)。之后,您可能会选择​​3210甚至导致中间洗牌,以减少分区数量,并可能会使某些机器和内核闲置,因为网络IO的增益(在该前期成本之后)大于CPU功率损失。

(唯一的情况是,我可以想到,从一开始就不分区的地方 - 因为你不能 - 当你的数据源是一个压缩文件时。)

还要注意,您可以在地图转换期间使用mapPartitionsmapPartitionsWithIndex保留分区。

最后,请记住,当你与你的分析实验,而你的工作你的方式到规模,有诊断能力,你可以使用:

  • toDebugString看到的血统RDD小号
  • getNumPartitions来,令人震惊,获得分区
  • glom的数清楚地看到你的数据被划分

如果您原谅无耻的插头,这些是我们在Analytics with Apache Spark讨论的事情。我们希望很快就有在线版本。

1

通过应用partitionBy先发制人你不避洗牌。你只是把它推到另一个地方。如果分区RDD重复使用多次,这可能是一个好主意,但是对于一次性连接,您没有任何收获。

如果我没有指定分区器,不会自动分区我的数据吗?

它将分区(又名洗牌)您的数据连接)和随后groupBy的一部分(除非你保持相同的密钥,并用它保留分区转换)。