Spark中如何高效的左加入?
How to efficiently left join in Spark?
我有两个表 - 一个包含所有 user_ids 及其属性,另一个包含唯一有趣的 user_ids 及其属性。我想查询它们以创建机器学习问题的训练集。
纯粹的SQL我会这样做:
select label, user_id, feature
from (
select 1 as label, user_id, feature
from interesting_table
UNION ALL
select 0 as label, a.user_id, a.feature
from alldata_table a
left join
interesting table b
on a.user_id = b.user_id
where b.user_id is null
)
在 Spark 中,从 interesting_table
拉取数据很容易,但 interesting_table
和 alldata_table
之间的左连接被证明是昂贵的。我应该
- 在sql中完全按照上面的操作,然后将结果提取为数据框?
- 创建
interesting_table
和 alldata_table
作为数据框并使用 .join() 运算符?
- 创建
interesting_table
和 alldata_table
作为数据框,通过否定 '.isin()'?[=31= 获得 interesting_df.user_id
和子集 alldata_df.user_id
的唯一成员]
- 还有别的吗?
我不确定这是最佳答案,但我最终在广播中使用了数据帧 API。
alldata_table = spark.table('alldata_table')
interesting_table = spark.table('interesting_table')
interesting_table.withColumnRenamed('user_id','user_id_interesting')
new_table = alldata_table.join(broadcast(interesting_table),
cond=[alldata_table['user_id']==interesting_table['user_id_interesting']],
how='left_outer')
new_table.filter(new_table['user_id_interesting'].isnull())
当然,这是假设 interesting_table
足够小,可以进行广播。据推测它可以减少到只有 user_id
字段以使其更小。
我有两个表 - 一个包含所有 user_ids 及其属性,另一个包含唯一有趣的 user_ids 及其属性。我想查询它们以创建机器学习问题的训练集。
纯粹的SQL我会这样做:
select label, user_id, feature
from (
select 1 as label, user_id, feature
from interesting_table
UNION ALL
select 0 as label, a.user_id, a.feature
from alldata_table a
left join
interesting table b
on a.user_id = b.user_id
where b.user_id is null
)
在 Spark 中,从 interesting_table
拉取数据很容易,但 interesting_table
和 alldata_table
之间的左连接被证明是昂贵的。我应该
- 在sql中完全按照上面的操作,然后将结果提取为数据框?
- 创建
interesting_table
和alldata_table
作为数据框并使用 .join() 运算符? - 创建
interesting_table
和alldata_table
作为数据框,通过否定 '.isin()'?[=31= 获得interesting_df.user_id
和子集alldata_df.user_id
的唯一成员] - 还有别的吗?
我不确定这是最佳答案,但我最终在广播中使用了数据帧 API。
alldata_table = spark.table('alldata_table')
interesting_table = spark.table('interesting_table')
interesting_table.withColumnRenamed('user_id','user_id_interesting')
new_table = alldata_table.join(broadcast(interesting_table),
cond=[alldata_table['user_id']==interesting_table['user_id_interesting']],
how='left_outer')
new_table.filter(new_table['user_id_interesting'].isnull())
当然,这是假设 interesting_table
足够小,可以进行广播。据推测它可以减少到只有 user_id
字段以使其更小。