了解 Spark 分区

Posted

技术标签:

【中文标题】了解 Spark 分区【英文标题】:Understanding Spark partitioning 【发布时间】:2017-04-26 20:47:58 【问题描述】:

我正在尝试了解 Spark 如何对数据进行分区。假设我有一个像图片中那样的执行 DAG(橙色框是阶段)。如果没有对 RDD 进行分区,这两个 groupByjoin 操作应该会非常繁重。

那么使用.partitonBy(new HashPartitioner(properValue)) 到 P1、P2、P3 和 P4 以避免洗牌是否明智?对现有 RDD 进行分区的成本是多少?什么时候不适合对现有 RDD 进行分区?如果我不指定分区程序,Spark 不会自动对我的数据进行分区吗?

谢谢

【问题讨论】:

【参考方案1】:

tl;dr 您的问题的答案分别是:如果可以,最好在一开始就进行分区;可能少于不分区;无论如何,您的RDD 以一种或另一种方式分区;是的。

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

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

但是,为了您的分析,通常您希望属于一起的数据(例如,具有相同键的数据,HashPartitioner 将适用)位于同一分区中,无论它们从哪里开始并在以后尽量减少洗牌。 Spark 还提供了RangePartitioner,或者您也可以根据自己的需要轻松滚动。但是你是对的,从默认分区到自定义分区有一个前期的洗牌成本;这几乎总是值得的。

通常一开始就分区是明智的(而不是用partitionBy 延迟不可避免的事情),然后如果以后需要repartition。稍后您甚至可以选择coalesce,这会导致中间洗牌,以减少分区数量并可能使一些机器和内核空闲,因为网络 IO 的收益(在前期成本之后)大于 CPU 的损失电源。

(我能想到的唯一一开始不分区的情况——因为你不能——是当你的数据源是压缩文件时。)

另请注意,您可以在映射转换期间使用 mapPartitionsmapPartitionsWithIndex 保留分区。

最后,请记住,当您尝试分析并逐步扩大规模时,您可以使用一些诊断功能:

toDebugString查看RDDs的血统 getNumPartitions 获取分区数,令人震惊 glom 看清楚你的数据是如何分区的

如果你原谅这个无耻的插件,这些就是我们在Analytics with Apache Spark 中讨论的事情。我们希望尽快有一个在线版本。

【讨论】:

【参考方案2】:

通过抢先应用partitionBy,您不会避免洗牌。你只是把它推到另一个地方。如果分区的 RDD 被多次重用,这可能是个好主意,但一次性连接没有任何好处。

如果我不指定分区器,Spark 不会自动对我的数据进行分区吗?

它会将您的数据分区(也称为 shuffle)作为连接的一部分)和后续的groupBy(除非您保留相同的密钥并使用保留分区的转换)。

【讨论】:

以上是关于了解 Spark 分区的主要内容,如果未能解决你的问题,请参考以下文章

spark分区

spark rdd分区数据支持哪些压缩格式

Apache spark如何计算分区以及在executor中如何处理分区

重要 | Spark分区并行度决定机制

跨集群分布分区

OpenMLDB: 一文了解窗口倾斜优化技术细节