我试图理解Distribute by
子句,以及如何在Spark-SQL
中使用它来优化Sort-Merge Joins
。在
根据我的理解,Spark Sql优化器将基于连接键(shuffle阶段)分布两个参与表(join)的数据集,以便在同一个分区中共同定位相同的键。如果是这样,那么如果我们在sql中使用distribute by
,那么我们也在做同样的事情。在
那么distribute by
可以用什么方式来改善连接性能呢?或者,在加载过程将数据写入磁盘时,使用distribute by
更好,这样使用此数据的后续查询就可以通过不必洗牌而从中受益?在
您能用一个真实的例子来解释一下在sparksql中使用distribute by/cluster by
来调整连接吗?在
让我试着回答你问题的每一部分:
是的,没错。在
有时您的一个表已经被分发,例如该表已被bucked或数据在join之前被同一个键聚合。在这种情况下,如果您显式地对第二个表(distributed by)进行重新分区,那么在join的两个分支中将实现相同的分区,并且Spark将不会在第一个分支中引发更多的shuffle(有时这被称为单边shuffle free join,因为shuffle只会发生在join的一个分支中,即你称之为重新分区/分发依据)。另一方面,如果不显式地重新划分另一个表,Spark将看到join的每个分支都有不同的分区,因此它将洗牌两个分支。所以在某些特殊情况下,调用repartition(distribute by)可以节省一次洗牌。在
请注意,要实现这一点,您还需要在两个分支中实现相同数量的分区。因此,如果您有两个表要在键
user_id
上联接,并且如果第一个表用这个键卡入10个存储桶,那么您需要用同一个键将另一个表也重新分区到10个分区中,然后连接将只有一个洗牌(在物理计划中,您可以看到只有一个表中有Exchange运算符)连接处的分支)。在好吧,这实际上被称为bucketing(cluster by),它允许你对数据进行一次预洗牌,然后每次你读数据并用bucketing的同一个键连接它(或聚合),它就不会被洗牌了。所以,是的,这是一种非常常见的技术,在保存数据时只需支付一次成本,然后在每次读取数据时利用它。在
相关问题 更多 >
编程相关推荐