了解 Spark 分区
Understanding Spark partitioning
我正在尝试了解 Spark 如何对数据进行分区。假设我有一个如图所示的执行 DAG(橙色框是阶段)。如果 RDD 没有分区,这两个 groupBy
和 join
操作应该非常繁重。
那么对 P1、P2、P3 和 P4 使用 .partitonBy(new HashPartitioner(properValue))
以避免随机播放是否明智?对现有 RDD 进行分区的成本是多少?什么时候不适合对现有的 RDD 进行分区?如果我不指定分区程序,Spark 不会自动对我的数据进行分区吗?
谢谢
通过先发制人地应用 partitionBy
,您无法避免随机播放。你只要把它推到另一个地方。如果分区的 RDD 被多次重用,这可能是个好主意,但对于一次性连接你什么也得不到。
Doesn't Spark partition my data automatically if I don't specify a partitioner?
它将分区(a.k.a.shuffle)你的数据成为连接的一部分)和随后的groupBy
(除非你保持相同的键并使用保留分区的转换)。
tl;dr 分别回答你的问题: 可以的话最好一开始就分区;可能小于不分区;无论如何,您的 RDD
以一种或另一种方式进行了分区;是的
这是一个相当宽泛的问题。它占据了我们课程的很大一部分!但是,让我们尝试在不写小说的情况下尽可能多地解决分区问题。
如您所知,使用像 Spark 这样的工具的主要原因是您有太多数据需要在一台机器上分析,而风扇的声音又不像喷气发动机。数据分布在集群中所有机器上的所有内核中,所以是的,有一个默认分区——根据数据。请记住,数据已经是静态分布的(在 HDFS、HBase 等中),因此 Spark 默认情况下只是根据相同的策略进行分区,以将数据保存在它们已经存在的机器上——默认分区数相等到集群上的核心数。您可以通过配置 spark.default.parallelism
覆盖此默认数量,并且您希望此数量为每台机器每个内核 2-3 个。
但是,通常您希望属于一起的数据(例如,具有相同键的数据,其中 HashPartitioner
适用)位于同一分区中,而不管它们从哪里开始,因为为了您的分析,并尽量减少以后的洗牌。 Spark 还提供了 RangePartitioner
,或者您可以很容易地根据自己的需要推出自己的。但是你是对的,从默认分区到自定义分区有一个前期的洗牌成本;这几乎总是值得的。
通常明智的做法是在一开始就进行分区(而不是用 partitionBy
延迟不可避免的事情),然后 repartition
如果以后需要的话。稍后您可能会选择 coalesce
even,这会导致中间洗牌,以减少分区数量并可能使一些机器和核心闲置,因为网络 IO 的收益(在前期成本之后)大于损失CPU 的力量。
(我能想到的唯一一开始不分区的情况——因为你不能——是当你的数据源是一个压缩文件时。)
另请注意,您可以使用 mapPartitions
和 mapPartitionsWithIndex
在地图转换期间保留分区。
最后,请记住,在扩大规模的过程中试验分析时,您可以使用以下诊断功能:
toDebugString
查看 RDD
s 的血统
getNumPartitions
令人震惊地得到分区数
glom
看清楚你的数据是如何分区的
如果你原谅无耻的插件,这些就是我们在 Analytics with Apache Spark 中讨论的事情。我们希望尽快有在线版本。
我正在尝试了解 Spark 如何对数据进行分区。假设我有一个如图所示的执行 DAG(橙色框是阶段)。如果 RDD 没有分区,这两个 groupBy
和 join
操作应该非常繁重。
.partitonBy(new HashPartitioner(properValue))
以避免随机播放是否明智?对现有 RDD 进行分区的成本是多少?什么时候不适合对现有的 RDD 进行分区?如果我不指定分区程序,Spark 不会自动对我的数据进行分区吗?
谢谢
通过先发制人地应用 partitionBy
,您无法避免随机播放。你只要把它推到另一个地方。如果分区的 RDD 被多次重用,这可能是个好主意,但对于一次性连接你什么也得不到。
Doesn't Spark partition my data automatically if I don't specify a partitioner?
它将分区(a.k.a.shuffle)你的数据成为连接的一部分)和随后的groupBy
(除非你保持相同的键并使用保留分区的转换)。
tl;dr 分别回答你的问题: 可以的话最好一开始就分区;可能小于不分区;无论如何,您的 RDD
以一种或另一种方式进行了分区;是的
这是一个相当宽泛的问题。它占据了我们课程的很大一部分!但是,让我们尝试在不写小说的情况下尽可能多地解决分区问题。
如您所知,使用像 Spark 这样的工具的主要原因是您有太多数据需要在一台机器上分析,而风扇的声音又不像喷气发动机。数据分布在集群中所有机器上的所有内核中,所以是的,有一个默认分区——根据数据。请记住,数据已经是静态分布的(在 HDFS、HBase 等中),因此 Spark 默认情况下只是根据相同的策略进行分区,以将数据保存在它们已经存在的机器上——默认分区数相等到集群上的核心数。您可以通过配置 spark.default.parallelism
覆盖此默认数量,并且您希望此数量为每台机器每个内核 2-3 个。
但是,通常您希望属于一起的数据(例如,具有相同键的数据,其中 HashPartitioner
适用)位于同一分区中,而不管它们从哪里开始,因为为了您的分析,并尽量减少以后的洗牌。 Spark 还提供了 RangePartitioner
,或者您可以很容易地根据自己的需要推出自己的。但是你是对的,从默认分区到自定义分区有一个前期的洗牌成本;这几乎总是值得的。
通常明智的做法是在一开始就进行分区(而不是用 partitionBy
延迟不可避免的事情),然后 repartition
如果以后需要的话。稍后您可能会选择 coalesce
even,这会导致中间洗牌,以减少分区数量并可能使一些机器和核心闲置,因为网络 IO 的收益(在前期成本之后)大于损失CPU 的力量。
(我能想到的唯一一开始不分区的情况——因为你不能——是当你的数据源是一个压缩文件时。)
另请注意,您可以使用 mapPartitions
和 mapPartitionsWithIndex
在地图转换期间保留分区。
最后,请记住,在扩大规模的过程中试验分析时,您可以使用以下诊断功能:
toDebugString
查看RDD
s 的血统
getNumPartitions
令人震惊地得到分区数glom
看清楚你的数据是如何分区的
如果你原谅无耻的插件,这些就是我们在 Analytics with Apache Spark 中讨论的事情。我们希望尽快有在线版本。