火花中的性能调优

时间:2020-04-25 16:28:18

标签: scala performance apache-spark

我正在运行一个火花作业,该作业处理大约2 TB的数据。处理过程涉及:

  1. 读取数据(avrò文件)
  2. 在属于地图类型的列上爆炸
  3. 爆炸列中的
  4. OrderBy
  5. 过滤DataFrame(我要过滤df的键集很小(有7个)(称为键集)。我做了df.filter(col("key").isin(keyset: _*) )
  6. 我将此df写到一个镶木地板上(此数据帧很小)
  7. 然后我再次针对不在键集中的所有键过滤原始数据帧 df.filter(!col("key").isin(keyset: _*) )并将其写入实木复合地板。这是更大的数据集。

原始avro数据约为2TB。处理大约需要1个小时。我想对其进行优化。我将在步骤3之后缓存数据帧,使用洗牌分区大小为6000。最小执行者= 1000,最大= 2000,执行者内存= 20 G,执行者核心=2。还有其他优化建议吗?左联接比过滤器性能更好吗?

3 个答案:

答案 0 :(得分:4)

一切对我来说都不错。 如果您的数据集很小,那么isin可以。

1)确保可以增加核心数量。执行者core = 5

不建议每个执行者使用5个以上的内核。这是基于一项研究的结果,任何具有5个以上并发线程的应用程序都会开始影响性能。

2)确保分区结构良好/统一。

示例(仅用于调试目的,不适用于生产):

  import org.apache.spark.sql.functions.spark_partition_id
  yourcacheddataframe.groupBy(spark_partition_id).count.show()

这将打印spark分区号和多少条记录 存在于每个分区中。以此为基础,如果您没有更多的并行性,则可以重新分区。

3)spark.dynamicAllocation.enabled可能是另一种选择。

例如:

spark-submit --conf spark.dynamicAllocation.enabled=true --conf spark.dynamicAllocation.cachedExecutorIdleTimeout=100 --conf spark.shuffle.service.enabled=true

连同所有其他所需的道具...多数民众赞成在那份工作。如果在spark-default.conf中提供这些道具,它将应用于所有作业。

使用上述所有这些选项,您的处理时间可能会减少。

答案 1 :(得分:0)

spark.dynamicAllocation.enabled已启用

分区大小非常不均匀(根据输出镶木地板零件文件的大小),因为我正在执行orderBy键,并且某些键比其他键更频繁。

键集是一个很小的集(7个元素)

答案 2 :(得分:0)

除了已提及的内容外,根据您的要求和群集,还提供了一些建议:

  1. 如果该作业可以在20g执行程序内存和5个内核上运行,则可以通过减少执行程序内存并保留5个内核来容纳更多工作人员
  2. 实际上需要订购吗? Spark确保行在分区内排序,但不在分区之间排序,这通常不是很有用。
  3. 文件是否必须位于特定位置?如果没有,请添加
df.withColumn("in_keyset", when( col('key').isin(keyset), lit(1)).otherwise(lit(0)). \
write.partitionBy("in_keyset").parquet(...)

可能会加快操作速度,以防止读入数据+爆炸2倍。 partitionBy确保键集中的项与其他键不在同一个目录中。