了解 Spark 分区
Posted
技术标签:
【中文标题】了解 Spark 分区【英文标题】:Understanding Spark partitioning 【发布时间】:2017-04-26 20:47:58 【问题描述】:我正在尝试了解 Spark 如何对数据进行分区。假设我有一个像图片中那样的执行 DAG(橙色框是阶段)。如果没有对 RDD 进行分区,这两个 groupBy
和 join
操作应该会非常繁重。
那么使用.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 的损失电源。
(我能想到的唯一一开始不分区的情况——因为你不能——是当你的数据源是压缩文件时。)
另请注意,您可以在映射转换期间使用 mapPartitions
和 mapPartitionsWithIndex
保留分区。
最后,请记住,当您尝试分析并逐步扩大规模时,您可以使用一些诊断功能:
toDebugString
查看RDD
s的血统
getNumPartitions
获取分区数,令人震惊
glom
看清楚你的数据是如何分区的
如果你原谅这个无耻的插件,这些就是我们在Analytics with Apache Spark 中讨论的事情。我们希望尽快有一个在线版本。
【讨论】:
【参考方案2】:通过抢先应用partitionBy
,您不会避免洗牌。你只是把它推到另一个地方。如果分区的 RDD 被多次重用,这可能是个好主意,但一次性连接没有任何好处。
如果我不指定分区器,Spark 不会自动对我的数据进行分区吗?
它会将您的数据分区(也称为 shuffle)作为连接的一部分)和后续的groupBy
(除非您保留相同的密钥并使用保留分区的转换)。
【讨论】:
以上是关于了解 Spark 分区的主要内容,如果未能解决你的问题,请参考以下文章