我想将火花数据帧分成两部分,并为每个子数据帧定义行号。但是我发现函数monotonically_increasing_id仍然会定义原始数据帧中的行号。
这是我在python中所做的:
# df is the original sparkframe
splits = df.randomSplit([7.0,3.0],400)
# add column rowid for the two subframes
set1 = splits[0].withColumn("rowid", monotonically_increasing_id())
set2 = splits[1].withColumn("rowid", monotonically_increasing_id())
# check the results
set1.select("rowid").show()
set2.select("rowid").show()
我希望两帧的rowid的前五个元素都是1到5(或0到4,不能清楚地记得):
set1: 1 2 3 4 5
set2: 1 2 3 4 5
但实际上我得到的是:
set1: 1 3 4 7 9
set2: 2 5 6 8 10
两个子帧的行id实际上是它们在原始sparkframe df中的行id而不是新的。
作为一个新的火花,我正在寻求帮助解决为什么会发生这种情况以及如何解决它。
答案 0 :(得分:0)
首先,您使用的是什么版本的Spark? monotonically_increasing_id
方法实现已更改几次。我可以在Spark 2.0中重现你的问题,但似乎火花2.2中的行为是不同的。所以它可能是一个在更新的火花释放中修复的错误。
话虽如此,您应该不期望monotonically_increasing_id
生成的值连续增加 。在您的代码中,我相信数据帧只有一个分区。根据{{3}}
保证生成的ID单调增加 独特,但不连续。 目前的实施方案 高31位中的分区ID,以及每个中的记录号 低33位分区。假设是数据框架 具有少于10亿个分区,每个分区少于8个 十亿条记录。
例如,考虑一个带有两个分区的DataFrame,每个分区都有3个分区 记录。该表达式将返回以下ID:0,1,2, 8589934592(1L<< 33),8589934593,8589934594。
因此,如果你的代码不应该期望rowid连续增加。
此外,您还应该考虑缓存场景和失败场景。即使monotonically_increase_id按预期工作 - 连续增加值,它仍然无法工作。如果节点出现故障怎么办?故障节点上的分区将从源或最后一个缓存/检查点重新生成,这可能具有不同的顺序,因此具有不同的rowid。逐出缓存也会导致问题。假设生成数据帧后将其缓存到内存中。如果被驱逐出内存怎么办?将来的操作将尝试再次重新生成数据帧,从而给出不同的rowid。