Apache spark 转换后我可以将分区器放回PairRDD吗?

Apache spark 转换后我可以将分区器放回PairRDD吗?,apache-spark,pyspark,Apache Spark,Pyspark,在大多数转换之后(例如values(),或toDF()),pairRDD的“partitioner”似乎被重置为None。然而,我的理解是,分区可能并不总是为这些转换而改变 由于cogroup和其他示例在已知分区是共分区的情况下执行效率更高,我想知道是否有办法告诉spark rdd仍然是共分区的 请参见下面的简单示例,其中我创建了两个共分区rdd,然后将它们转换为DFs,并对结果rdd执行cogroup。类似的例子可以使用值,然后再添加正确的对 虽然这个例子很简单,但我的实际情况是,可能我加载了

在大多数转换之后(例如
values()
,或
toDF()
),pairRDD的“partitioner”似乎被重置为None。然而,我的理解是,分区可能并不总是为这些转换而改变

由于cogroup和其他示例在已知分区是共分区的情况下执行效率更高,我想知道是否有办法告诉spark rdd仍然是共分区的

请参见下面的简单示例,其中我创建了两个共分区rdd,然后将它们转换为DFs,并对结果rdd执行
cogroup
。类似的例子可以使用值,然后再添加正确的对

虽然这个例子很简单,但我的实际情况是,可能我加载了两个具有相同分区的拼花地板数据帧

这可能吗?在这种情况下会不会带来性能优势

data1 = [Row(a=1,b=2),Row(a=2,b=3)]
data2 = [Row(a=1,c=4),Row(a=2,c=5)]
rdd1 = sc.parallelize(data1)
rdd2 = sc.parallelize(data2)

rdd1 = rdd1.map(lambda x: (x.a,x)).partitionBy(2)
rdd2 = rdd2.map(lambda x: (x.a,x)).partitionBy(2)

print(rdd1.cogroup(rdd2).getNumPartitions()) #2 partitions

rdd3 = rdd1.toDF(["a","b"]).rdd
rdd4 = rdd2.toDF(["a","c"]).rdd

print(rdd3.cogroup(rdd4).getNumPartitions()) #4 partitions (2 empty)

scala
api中,大多数转换包括

preservesPartitioning=true
选择权。一些python RDDAPI保留了这一功能:但例如

groupBy
这是一个重大的例外。就
Dataframe
API而言,分区方案似乎大多不在最终用户的控制范围内,甚至在
scala
端也是如此

因此,您可能必须:

  • 限制自己使用RDD,即避免使用数据帧/数据集方法
  • 选择哪种RDD转换要有选择:看看哪些转换是允许的

    • 保留父级的分区方案
    • 使用PreserveSpatiting=true

这是有道理的。查看用于保存分区的scala代码,它似乎只是保存了分区器对象。在一个或多个转换之后,我无法手动重新附加它吗?@retrocookie分区器是每个转换的一个组成部分,因此需要在此时指定以获得非默认行为。默认情况下,一些spark方法保留了父分区,但SQL/dataframes在许多情况下不保留。我仍然觉得缺少一些解释。如果我将一个分区的RDD(没有分区器)转换回PairRDD,并且我知道如何通过分区分配密钥,那么我应该能够(便宜地)告诉spark它仍然有相同的分区器。类似地,是否有内在原因
toDF
values
不能使用相同的参数保留分区?毕竟对于
值的情况
,我可以通过
映射实现相同的功能
@retrocookie“应该”是正确的:但“可以”不一定是正确的。我回答的要点是,必须(a)检查api是否提供
preservespatiting
参数,以及(b)如果不提供,则深入研究Spark源代码,看看它们在默认情况下做了什么。对于(b)项,有各种各样的实际方法。对于Spark SQL,作者告诉我,他们倾向于避免重复使用父分区,因为新手可能会误用。我希望为高级用户提供分区API,但对于spark sql(/dataframes),它还没有到位。