迫使pyspark加入更快发生

时间:2017-11-21 21:37:49

标签: apache-spark pyspark lazy-evaluation

问题:我有两张大小差异很大的桌子。我想通过左外连接加入一些id。不幸的是,出于某种原因,甚至在缓存后我的操作在连接之后执行所有记录,即使我只想要左表中的那些。见下文:

我的问题:  1.我如何设置它以便只通过昂贵的争吵步骤处理与左表匹配的记录?

LARGE_TABLE => ~900M记录

SMALL_TABLE => 500K记录

CODE:

combined = SMALL_TABLE.join(LARGE_TABLE SMALL_TABLE.id==LARGE_TABLE.id, 'left-outer')
print(combined.count())
...
...
# EXPENSIVE STUFF!
w = Window().partitionBy("id").orderBy(col("date_time"))
data = data.withColumn('diff_id_flag', when(lag('id').over(w) != col('id'), lit(1)).otherwise(lit(0)))

不幸的是,我的执行计划显示上述昂贵的转换操作正在~900M记录上完成。我发现这很奇怪,因为我运行df.count()来迫使连接急切而不是懒惰地执行。

任何想法?

其他资料:   - 请注意,我的代码流中的昂贵转换发生在连接之后(至少这是我解释它的方式)但是我的DAG显示了作为连接的一部分发生的昂贵转换。这正是我想要避免的,因为转换是昂贵的。我希望连接执行,然后该连接的结果将通过昂贵的转换运行。   - 假设较小的表不适合内存。

2 个答案:

答案 0 :(得分:0)

执行此操作的最佳方法是broadcast微小的数据帧。缓存适用于多个操作,这些操作似乎不适用于您的特定用例。

答案 1 :(得分:0)

  • df.count对执行计划完全没有影响。没有任何充分理由,这只是昂贵的操作。
  • 此处的窗口函数应用程序需要与join相同的逻辑。由于您按idpartitionBy id加入,因此两个阶段都需要对双方进行相同的散列分区和完整数据扫描。将这两者分开是没有可接受的理由。

    实际上join逻辑应该在窗口之前应用,作为同一阶段下游转换的过滤器。