我有4列(c1, c2, c3, c4)
的数据集。
我按(c1, c2)
分组并执行了一些汇总。
如果之后我按(c1)
分组,这个分组操作会因为之前的分组而更有效吗?
答案 0 :(得分:1)
截至今天(Spark 2.1)这样的结构未被优化器使用:
Seq.empty[(Int, Int, Int)].toDF("c1", "c2", "c3")
.groupBy($"c1", $"c2")
.sum("c3")
.groupBy($"c1")
.avg($"c3")
.explain
== Physical Plan ==
*HashAggregate(keys=[c1#130], functions=[avg(c3#142L)])
+- Exchange hashpartitioning(c1#130, 200)
+- *HashAggregate(keys=[c1#130], functions=[partial_avg(c3#142L)])
+- *HashAggregate(keys=[c1#130, c2#131], functions=[sum(cast(c3#132 as bigint))])
+- Exchange hashpartitioning(c1#130, c2#131, 200)
+- *HashAggregate(keys=[c1#130, c2#131], functions=[partial_sum(cast(c3#132 as bigint))])
+- LocalTableScan <empty>, [c1#130, c2#131, c3#132]
正如您所看到的,Spark会为两个聚合调度两个独立的Exchanges
,而不是使用更一般的分组。所以在实践中答案取决于两个因素:
聚合功能。如果函数以恒定的内存占用量运行并应用&#34; map-side&#34;减少(如sum
)然后较低的熵可以增加可以在本地减少的数据量并减少随机播放的大小。
值分布。 c1
基数必须足够高,才能将多个(c1, c2)
级别分配给第一个聚合中的单个分区。如果每个分区的每c1
值减少,则无法获得任何收益。
如果满足这两个条件,您应该会看到一些性能提升。