【发布时间】:2019-12-10 23:27:29
【问题描述】:
有两个数据框。一个 - df_table_a 是通过直接从 Hive 表中读取来创建的。
另一个 - df_table_a_slow 是通过在 df_table_a 之上应用 UDF 转换创建的
df_table_a = spark.sql('SELECT INT_COL, DATE_WEEK FROM table_a')
shift_date_udf = F.udf(lambda day: day - pd.offsets.Week(3, weekday=0), DateType())
df_table_a_slow = df_fast.withColumn('DATE_WEEK', shift_date_udf('DATE_WEEK'))
然后是 df_table_b 数据框,它也是通过直接从 Hive 表中读取来创建的。
df_table_b = spark.sql('SELECT INT_COL, DATE_WEEK, OTHER_COLUMN FROM table_b')
现在我们将df_table_b 加入到上面定义的两个数据帧中。
df_fast_join = df_table_a.join(df, on=['INT_COL', 'DATE_WEEK'], how='left')
df_slow_join = df_table_a_slow.join(df, on=['INT_COL', 'DATE_WEEK'], how='left')
我想计算两个连接的执行时间,所以这里有一个函数来估计转换时间:
def time_transformation(df, subject):
start = time.time()
cnt = df.count()
end = time.time()
print(f'>>> {subject} - {cnt}', end - start)
结果:
time_transformation(df_fast_join, 'fast join')
>> fast join - 75739267 37.43
time_transformation(df_slow_join, 'slow join')
>> slow join - 75739267 553.32
UDF 转换本身似乎不需要太多时间:
time_transformation(df_slow, 'df_slow')
>> df_slow - 75739267 0.25
两个连接的执行计划相差一行:
+- BatchEvalPython [<lambda>(DATE_WEEK#1)], [INT_COL#0, DATE_WEEK#1, pythonUDF0#843]
问题:为什么将 UDF 应用于其中一个数据帧会使连接速度减慢 10 倍以上?怎么解决?
【问题讨论】:
-
udf 不是 spark 中的自然函数,因此它总是比通常的 spark 过程慢。即使您认为这是一项非常简单且微不足道的工作,但实际上还没有达到火花。
-
我怀疑
df_slow实际上没有进行任何计算,这就是为什么它看起来很快,但尝试进行收集,这会慢很多
标签: apache-spark pyspark apache-spark-sql