为什么以本地模式加入Spark太慢了?

Bha*_*rla 5 apache-spark apache-spark-sql pyspark spark-dataframe

我在本地模式下使用spark,简单的连接花了太长时间。我已经获取了两个数据帧:A(8列和230万行)和B(8列和120万行),并使用A.join(B,condition,'left')并最终将它们联接起来,称为动作。它创建一个包含三个阶段的作业,每个阶段用于提取两个数据帧,一个用于联接。令人惊讶的是,提取数据帧A的阶段大约需要8分钟,而提取数据帧B的阶段大约需要1分钟。加入只需几秒钟。我的重要配置设置为:

  1. spark.master本地[*]
  2. spark.driver.cores 8
  3. spark.executor.memory 30克
  4. spark.driver.memory 30克
  5. spark.serializer org.apache.spark.serializer.KryoSerializer
  6. spark.sql.shuffle.partitions 16

唯一的执行者是驱动程序本身。在提取数据帧时,我将其划分为32个部分(也尝试了16,64,50,100,200个)。我已经看到带有数据帧A提取的阶段的随机写入内存为100 MB。因此,为避免混洗,我对数据帧和广播的数据帧B(较小)都做了16个初始分区,但这没有帮助。仍然有随机写入存储器。我broadcast(B)为此使用了语法。难道我做错了什么?为什么改组仍然存在?另外,当我看到事件时间表时,在任何时间点仅显示四个内核正在处理。虽然我有一台2core * 4处理器的机器。为什么?

Dan*_*kyy 2

简而言之,“加入”<=>洗牌,这里的大问题是数据在分区上分布的均匀程度(例如参见https://0x0fff.com/spark-architecture-shuffle/https://www.slideshare .net/SparkSummit/handling-data-skew-adaptively-in-spark-using-dynamic-repartitioning并通过 Google 搜索问题)。提高效率的可能性很少:

  • 更多地考虑您的数据(A 和 B)并明智地分区数据;
  • 分析一下,你的数据有偏差吗?
  • 进入 UI 并查看任务计时;
  • 为分区选择这样的键,在“连接”期间,只有数据集 A 中的几个分区与 B 的几个分区进行混洗;