我们常见的Spark处理流程是这样的:
装载:
rdd = sqlContext.parquetFile("mydata/")
rdd = rdd.map(lambda row: (row.id,(some stuff)))
rdd = rdd.filter(....)
rdd = rdd.partitionBy(rdd.getNumPatitions())
按id
处理(这就是我们执行partitionBy
以上的原因!)
rdd.reduceByKey(....)
rdd.join(...)
但是,Spark 1.3将sqlContext.parquetFile
更改为DataFrame
而不是RDD
,并且它不再具有partitionBy
,getNumPartitions
和{{1方法。
我们现在使用reduceByKey
做什么?
我们可以用
之类的东西替换加载代码partitionBy
并使用rdd = sqlContext.parquetFile("mydata/").rdd
rdd = rdd.map(lambda row: (row.id,(some stuff)))
rdd = rdd.filter(....)
rdd = rdd.partitionBy(rdd.getNumPatitions())
df = rdd.map(lambda ...: Row(...)).toDF(???)
代替groupBy
。
这是正确的方法吗?
PS。是的,我了解reduceByKey
等人partitionBy
。但是,如果没有先前的groupBy
,每个 partitionBy
,join
& c可能必须执行跨节点操作。我正在寻找一种方法保证所有需要按我的密钥分组的操作都会运行本地。
答案 0 :(得分:1)
看来,由于版本 1.6 ,repartition(self, numPartitions, *cols)
可以满足我的需求:
.. versionchanged:: 1.6
添加了可选参数以指定分区列。 如果指定了分区列,也会使
numPartitions
成为可选项。
答案 1 :(得分:0)
由于DataFrame
为我们提供了表和列对RDD
的抽象,因此操作DataFrame
的最便捷方法是使用这些抽象以及DataFrame支持我们的特定表操作方法。
在DataFrame上,我们可以:
select()
\ udf()
\ as()
filter()
或where()
groupBy()
和agg()
sample()
\ join()
\ union()
saveAsTable()
\ saveAsParquet()
\ insertIntoJDBC()
有关详细信息,请参阅Spark SQL and DataFrame Guide。
因此,常见的工作如下:
val people = sqlContext.parquetFile("...")
val department = sqlContext.parquetFile("...")
people.filter("age > 30")
.join(department, people("deptId") === department("id"))
.groupBy(department("name"), "gender")
.agg(avg(people("salary")), max(people("age")))
根据您的具体要求,这可能如下所示:
val t = sqlContext.parquetFile()
t.filter().select().groupBy().agg()