如何处理火花中强烈变化的数据大小

时间:2017-06-28 05:14:34

标签: apache-spark

我想知道设计火花作业的最佳做法,其中数据量未提前知道(或变化很大)。在我的例子中,应用程序应该处理初始加载,然后处理增量数据。

我想知道如何设置数据中的分区数(例如使用repartition或设置spark.sql.shuffle.partitions等参数,以避免执行程序中的OOM重复(为每个分配的内存提供固定数量)执行人)我可以

  1. 定义了非常多的分区,以确保即使在非常高的工作负载下,作业也不会失败
  2. 根据源数据的大小设置运行时的分区数
  3. 在独立的数据块上引入迭代(即循环)
  4. 在所有选项中,我都会看到问题:

    1:我认为这对于小数据量来说效率很低,因为这个数据非常小

    2:需要额外的查询(例如count),例如要设置spark.sql.shuffle.partitionsSparkContext需要重新启动,我想避免

    3:似乎与Spark的精神相矛盾

    所以我想知道对于强烈变化的数据量,最有效的策略是什么。

    编辑: 我设置spark.sql.shuffle.partitions是错误的,这可以在运行时设置woutout重新启动spark context

1 个答案:

答案 0 :(得分:0)

  1. 如果不知道需要,请不要设置大量分区。你绝对会扼杀你工作的表现。
  2. 如你所说,不要循环!
  3. 正如您所提到的,您引入了一个额外的步骤来计算您的数据,乍一看似乎是错误的。但是,您不应该将此视为误用计算。通常,如果对数据进行严格分区,计算数据所需的时间远远少于进行进一步处理所需的时间。将计数操作视为投资,它当然值得。

    您无需通过配置设置分区并重新启动Spark。相反,请执行以下操作:

    1. 注意RDD / Dataframe / Dataset的当前分区数
    2. 计算数据中的条目/行数
    3. 根据平均行大小的估算值,计算目标分区数
    4. 如果#targetPartitions<< #actualPartitions然后合并
    5. 否则如果#targetPartitions>> #actualPartitions然后重新分区
    6. 其他#targetPartitions~ = #actualPartitions然后什么都不做
    7. 合并操作将重新分区您的数据而不会改组,因此当它可用时效率更高。

      理想情况下,您可以估算要生成的行数,而不是计算它们。此外,您需要仔细考虑何时适合执行此操作。使用较长的RDD谱系可以消除性能,因为由于scala延迟执行,您可能会无意中减少可执行复杂代码的核心数。查看检查点以缓解此问题。