tl;dr 您的问题的答案分别是:如果可以,最好在一开始就进行分区;可能少于不分区;无论如何,您的RDD 以一种或另一种方式分区;是的。
这是一个相当广泛的问题。它占据了我们课程的很大一部分!但是,让我们尝试在不写小说的情况下尽可能多地解决分区问题。
如您所知,使用 Spark 这样的工具的主要原因是您有太多数据需要在一台机器上进行分析,而风扇的声音又不像喷气发动机。数据分布在集群中所有机器上的所有核心中,所以是的,有一个默认分区——根据数据。请记住,数据已经静态分布(在 HDFS、HBase 等中),因此 Spark 默认情况下只是根据相同的策略进行分区,以将数据保留在它们已经存在的机器上——默认分区数相等到集群上的核心数。您可以通过配置 spark.default.parallelism 来覆盖此默认数字,并且您希望此数字为每台机器每个内核 2-3 个。
但是,为了您的分析,通常您希望属于一起的数据(例如,具有相同键的数据,HashPartitioner 将适用)位于同一分区中,无论它们从哪里开始并在以后尽量减少洗牌。 Spark 还提供了RangePartitioner,或者您也可以根据自己的需要轻松滚动。但是你是对的,从默认分区到自定义分区有一个前期的洗牌成本;这几乎总是值得的。
通常一开始就分区是明智的(而不是用partitionBy 延迟不可避免的事情),然后如果以后需要repartition。稍后您甚至可以选择coalesce,这会导致中间洗牌,以减少分区数量并可能使一些机器和内核空闲,因为网络 IO 的收益(在前期成本之后)大于 CPU 的损失电源。
(我能想到的唯一一开始不分区的情况——因为你不能——是当你的数据源是压缩文件时。)
另请注意,您可以在映射转换期间使用 mapPartitions 和 mapPartitionsWithIndex 保留分区。
最后,请记住,当您尝试分析并逐步扩大规模时,您可以使用一些诊断功能:
-
toDebugString查看RDDs的血统
-
getNumPartitions 获取分区数,令人震惊
-
glom 看清楚你的数据是如何分区的
如果你原谅这个无耻的插件,这些就是我们在Analytics with Apache Spark 中讨论的事情。我们希望尽快有一个在线版本。