在 Spark 数据框中生成可重复的唯一 ID

cas*_*sen 2 python apache-spark apache-spark-sql pyspark

我们有一个包含大量文件的数据湖,我可以在其中读取这些文件的内容及其路径:

sdf = spark.read.load(source)\
  .withColumn("_path", F.input_file_name())
Run Code Online (Sandbox Code Playgroud)

我想为每一行生成一个唯一的 ID,以便更轻松地在表之间进行下游连接,并且我希望该 ID 在运行之间可重现。


最简单的方法是简单地使用_path列作为标识符。

sdf = spark.read.load(source)\
  .withColumn("_path", F.input_file_name())
Run Code Online (Sandbox Code Playgroud)

然而,拥有某种整数表示形式会“更漂亮”且更紧凑。对于其他表,唯一标识符可能是几列的组合,这会让情况变得更加丑陋。

另一种方法是使用单调递增的 ID

sdf.withColumn("id", F.monotonically_increasing_id())
Run Code Online (Sandbox Code Playgroud)

但是,在此解决方案中,不能保证运行分析时 id=2 也在一周后(新数据到达时)运行分析时 id=2。

第三种方法是使用哈希函数:

sdf.withColumn("id", F.col("_path"))
Run Code Online (Sandbox Code Playgroud)

这可能非常好,因为很容易对列的组合进行散列,但这并不稳定,因为多个输入可以给出相同的输出:

对我们的实际数据进行此类分析,得出来自单个来源的 396,702 个哈希 ID _path,以及来自两个路径的 24 个哈希 ID。因此碰撞率为 0.006%。

我们可以简单地忽略这极小部分的数据,但一定有一种更优雅的方式来实现我想要实现的目标?

mck*_*mck 5

您可以尝试xxhash64Spark SQL 中的哈希,它提供 64 位哈希值,并且对于哈希冲突应该更稳健:

sdf.withColumn("id", F.expr("xxhash64(_path)"))
Run Code Online (Sandbox Code Playgroud)

或者使用更强大的哈希算法,

sdf.withColumn("id", F.expr("conv(sha2(_path,256),16,10)"))
Run Code Online (Sandbox Code Playgroud)