Apache spark 火花拼花地板零件号不连续?

Apache spark 火花拼花地板零件号不连续?,apache-spark,pyspark,parquet,partition,Apache Spark,Pyspark,Parquet,Partition,我正在使用spark 3.0转换和排序数据。让我担心的是,我将数据划分为250个存储桶,排序然后保存。我在输出目录中看到的通常是160个文件,文件名以part-0000-**开头,但编号顺序不一致: part-00000-f667f314-69f2-40d0-ba8a-b5b934650158-c000.gz.parquet part-00002-f667f314-69f2-40d0-ba8a-b5b934650158-c000.gz.parquet part-00005-f667f314-69

我正在使用spark 3.0转换和排序数据。让我担心的是,我将数据划分为250个存储桶,排序然后保存。我在输出目录中看到的通常是160个文件,文件名以part-0000-**开头,但编号顺序不一致:

part-00000-f667f314-69f2-40d0-ba8a-b5b934650158-c000.gz.parquet
part-00002-f667f314-69f2-40d0-ba8a-b5b934650158-c000.gz.parquet
part-00005-f667f314-69f2-40d0-ba8a-b5b934650158-c000.gz.parquet
那么第1、3和4部分发生了什么?这在整个文件中都会发生。我是否丢失了数据,或者出于某种原因正在合并分区?代码如下:

 df = df.withColumn("bucket", F.abs(F.col("Id")) % F.lit(250))
 df = df.repartition(250,"bucket")
 df = df.sortWithinPartitions("id")
 df.write.option("compression", "gzip").parquet(outputPath)

您需要查看id列的分布情况。在第一行中,您正在使用250对if id进行模运算,这意味着如果值1、3、4等不存在,则不会创建这些id。在下一步中,您将使用
repartition
函数创建250个分区。其中一些分区可能是空的


您可以尝试执行
df.repartition(“bucket”)
,这将创建至少200个分区,这是默认的分区值。如果您希望不获得任何间隙,则可以进行计数,并在此基础上使用重新分区。

您需要查看id列的分布情况。在第一行中,您正在使用250对if id进行模运算,这意味着如果值1、3、4等不存在,则不会创建这些id。在下一步中,您将使用
repartition
函数创建250个分区。其中一些分区可能是空的


您可以尝试执行
df.repartition(“bucket”)
,这将创建至少200个分区,这是默认的分区值。如果您想获得无间隙,则可以进行计数并在此基础上使用重新分区。

如果您想获得无间隙的分区ID,则必须确保分区的数量与唯一分区键值的数量匹配(或通常小于或等于):

df = df.withColumn("bucket", F.abs(F.col("Id")) % F.lit(250))
nkeys = df.select("bucket").distinct().count()
df = df.repartition(nkeys, "bucket")
df = df.sortWithinPartitions("id")
df.write.option("compression", "gzip").parquet(outputPath)

另外,请注意,缺少某些分区id意味着这些分区是空的,这意味着您的
id
值具有特定的分布。根据您想要重新划分数据的原因,使用
id
列(
df.repartition(250,“id”)
)更有可能为您提供大小几乎相等的250个分区。这是因为Spark实际上使用分区键的散列,而散列函数更有可能将原始分布转换为统一分布。

如果您想获得没有间隙的分区ID,必须确保分区数匹配(或通常小于或等于)唯一分区键值的数目:

df = df.withColumn("bucket", F.abs(F.col("Id")) % F.lit(250))
nkeys = df.select("bucket").distinct().count()
df = df.repartition(nkeys, "bucket")
df = df.sortWithinPartitions("id")
df.write.option("compression", "gzip").parquet(outputPath)

另外,请注意,缺少某些分区id意味着这些分区是空的,这意味着您的
id
值具有特定的分布。根据您想要重新划分数据的原因,使用
id
列(
df.repartition(250,“id”)
)更有可能为您提供大小几乎相等的250个分区。这是因为Spark实际上使用分区键的散列,而散列函数更有可能将原始分布转换为统一分布。

df.repartition(“bucket”)和
df.repartition(250,“bucket”)
之间的唯一区别是前者使用默认的分区数,除非另有配置,否则为200。这并没有改变这样一个事实,即许多分区可能是空的,并且ID中可能(而且很可能会)有间隙。编写测试代码很简单。谢谢。这是有道理的。有250万个唯一ID,该ID实际上是一个64位哈希。我希望分布均匀,但正如您所说,不能保证每个桶都有ID,但对我来说很容易test@HristoIliev-是的,你是对的,我忘了提到。写。分区(COL)如果目录的数量是基于COL.@Jayadeep Jayaraman的唯一值创建的,那么我不使用分区写入的原因是,这似乎破坏了排序,这是过程中最重要的部分。是的,我看到了您的初始帖子,并且看到您正在写入一个非分区表。如果这个答案有用,请接受我的答案。
df.repartition(“bucket”)
df.repartition(250,“bucket”)
之间唯一的区别是前者使用默认的分区数,除非另有配置,否则默认的分区数是200。这并没有改变这样一个事实,即许多分区可能是空的,并且ID中可能(而且很可能会)有间隙。编写测试代码很简单。谢谢。这是有道理的。有250万个唯一ID,该ID实际上是一个64位哈希。我希望分布均匀,但正如您所说,不能保证每个桶都有ID,但对我来说很容易test@HristoIliev-是的,你是对的,我忘了提到。写。分区(COL)如果目录的数量是基于COL.@Jayadeep Jayaraman的唯一值创建的,那么我不使用分区写入的原因是,这似乎破坏了排序,这是过程中最重要的部分。是的,我看到了您的初始帖子,并且看到您正在写入一个非分区表。如果这个答案有用,请接受我的回答。我感谢你的回答。这个Id实际上是一个xx64(spark 3.0)哈希,所以我希望它是统一的。我将不得不研究250万xx64哈希的分布为何不那么均匀。我不知道;实际上,我并不关心顺序文件名,我只是担心数据丢失。这反过来又使我对id哈希产生了疑问。我感谢你的回答。这个Id实际上是一个xx64(spark 3.0)哈希,所以我希望它是统一的。我将不得不研究250万xx64哈希的分布为何不那么均匀。我不知道;实际上,我并不关心顺序文件名,我只是担心数据丢失。这反过来又让我质疑id哈希。