额,关于笛卡尔积CartesianProduct

2022-11-25 20:01:11 浏览数 (2)

  • 笛卡尔积会产生shuffle吗?
  • 有关窄依赖解惑
  • 最后送一道面试题

1、笛卡尔积会产生shuffle吗?

结论是:不会

如果从网上搜的话,排在前几的答案,基本都是这样:

但是仔细分析笛卡尔积源码,就会发现,它的运行原理是这样的:

代码语言:javascript复制
select tmp1.a,tmp2.b from testdata2 tmp1 join testdata2 tmp2 

== executedPlan ==
CartesianProduct
:- SerializeFromObject [knownnotnull(assertnotnull(input[0, org.apache.spark.sql.test.SQLTestData$TestData2, true])).a AS a#3]
:   - Scan[obj#2]
 - SerializeFromObject [knownnotnull(assertnotnull(input[0, org.apache.spark.sql.test.SQLTestData$TestData2, true])).b AS b#12]
    - Scan[obj#10]

笛卡尔积的分片方法:

getDependencies方法:

整个过程在map端执行,没有shuffle

2、有关窄依赖

这个如果在百度上搜相关内容,大部分都这么定义:

如果这样理解的话,就会很矛盾,笛卡尔积的依赖中,一个父RDD的分区明明被多个子RDD的分区消费了,可它是窄依赖

我们看窄依赖的源码:

代码语言:javascript复制
**
 * :: DeveloperApi ::
 * Base class for dependencies where each partition of the child RDD depends on a small number
 * of partitions of the parent RDD. Narrow dependencies allow for pipelined execution. * 
 */
@DeveloperApi
abstract class NarrowDependency[T](_rdd: RDD[T]) extends Dependency[T] {
  /**
   * Get the parent partitions for a child partition.
   * @param partitionId a partition of the child RDD
   * @return the partitions of the parent RDD that the child partition depends upon
   */
  def getParents(partitionId: Int): Seq[Int]

  override def rdd: RDD[T] = _rdd
}

从这个注释上来看,应该这么翻译:其中子RDD的每个分区依赖于父RDD的小部分区

后来,我就想网上的说法是怎么来的呢?

翻了之前版本的源码,发现了出处:

spark1.0版本的窄依赖注释:其中父RDD的每个分区最多由子RDD的一个分区使用

所以,我想,恐怕现在网上流行的都是spark1.0版本的窄依赖定义,现在已经进化到spark3了,应该以最新来

3、给一道面试题吧

join一定会发生shuffle吗?

不一定,下面这些情况下join不会产生shuffle

  • 笛卡尔积
  • BroadcastHashJoin
  • BroadcastNestedLoopJoin
  • 使用相同的分区器进行一次分区然后再去join,这时join不会发生shuffle

没有特别标准的答案,重要的是多积累,把自己平时遇到的,学到的一点点积累下来,慢慢的就变成了自己的底蕴

0 人点赞