Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 按列进行Spark重新分区,每列具有动态分区数_Apache Spark - Fatal编程技术网

Apache spark 按列进行Spark重新分区,每列具有动态分区数

Apache spark 按列进行Spark重新分区,每列具有动态分区数,apache-spark,Apache Spark,如何根据列中的项数对数据帧进行分区。假设我们有一个100人的数据框(列是名字和国家),我们想为一个国家的每10个人创建一个分区 如果我们的数据集包含80个中国人、15个法国人和5个古巴人,那么我们需要8个中国分区、2个法国分区和1个古巴分区 以下是无法工作的代码: df.repartition($“country”):这将为中国创建一个分区,为法国创建一个分区,为古巴创建一个分区 df.repartition(8,$“country”,rand):这将为每个国家创建最多8个分区,因此应该为中国

如何根据列中的项数对数据帧进行分区。假设我们有一个100人的数据框(列是
名字
国家
),我们想为一个国家的每10个人创建一个分区

如果我们的数据集包含80个中国人、15个法国人和5个古巴人,那么我们需要8个中国分区、2个法国分区和1个古巴分区

以下是无法工作的代码:

  • df.repartition($“country”)
    :这将为中国创建一个分区,为法国创建一个分区,为古巴创建一个分区
  • df.repartition(8,$“country”,rand)
    :这将为每个国家创建最多8个分区,因此应该为中国创建8个分区,但法国和古巴分区未知。法国可以分为8个分区,古巴可以分为5个分区。有关更多详细信息,请参阅
以下是
repartition()
文档:

当我查看
repartition()
方法时,我甚至没有看到一个包含三个参数的方法,因此看起来有些行为没有记录在案


有没有办法动态设置每列的分区数?这将使创建分区数据集变得更加容易。

由于spark分区数据的方式,您将无法准确地完成这一任务。Spark获取在重新分区中指定的列,将该值散列为64b长,然后按分区数对该值进行模化。这样,分区的数量是确定的。它以这种方式工作的原因是,除了确保哈希在连接的左侧和右侧相同外,连接还需要在连接的左侧和右侧匹配数量的分区

“我们希望为一个国家的每10个人创建一个分区。”

你到底想在这里完成什么?分区中只有10行可能会对性能造成严重影响。您是否正在尝试创建分区表,其中分区中的每个文件都被保证只有x行数

“df.重新分区($“国家”):这将为中国创建一个分区,为法国创建一个分区,为古巴创建一个分区”

这将实际创建一个数据帧,其中默认的随机分区数按国家散列

  def repartition(partitionExprs: Column*): Dataset[T] = {
    repartition(sparkSession.sessionState.conf.numShufflePartitions, partitionExprs: _*)
  }
“df.repartition(8,$“country”,rand):这将为每个国家创建最多8个分区,因此它应该为中国创建8个分区,但法国和古巴分区未知。法国可以在8个分区中,古巴可以在5个分区中。有关详细信息,请参阅此答案。”


像怀斯一样,这是一个微妙的错误。在这8个分区中,只有8个分区的国家基本上是随机排列的。

下面的代码将为每个数据文件创建10行():

以下是Spark 2.2之前的代码,它将为每个数据文件创建大约10行:

val desiredRowsPerPartition = 10

val joinedDF = df
  .join(countDF, Seq("person_country"))
  .withColumn(
    "my_secret_partition_key",
    (rand(10) * col("count") / desiredRowsPerPartition).cast(IntegerType)
  )

val outputPath = new java.io.File("./tmp/partitioned_lake6/").getCanonicalPath
joinedDF
  .repartition(col("person_country"), col("my_secret_partition_key"))
  .drop("count", "my_secret_partition_key")
  .write
  .partitionBy("person_country")
  .csv(outputPath)

关于第二次调用中的3个参数,
$“country”,rand
一起作为
partitionExprs
感谢您指出我的细微错误。对于10行,不需要此代码,但在倾斜的大型数据集上创建分区数据湖时,这非常重要。
val desiredRowsPerPartition = 10

val joinedDF = df
  .join(countDF, Seq("person_country"))
  .withColumn(
    "my_secret_partition_key",
    (rand(10) * col("count") / desiredRowsPerPartition).cast(IntegerType)
  )

val outputPath = new java.io.File("./tmp/partitioned_lake6/").getCanonicalPath
joinedDF
  .repartition(col("person_country"), col("my_secret_partition_key"))
  .drop("count", "my_secret_partition_key")
  .write
  .partitionBy("person_country")
  .csv(outputPath)