1

我读过这个问题,其中 OP 试图转换这个逻辑计划:

Aggregate [sum(inc(vals#4L)) AS sum(inc(vals))#7L]
+- LocalRelation [vals#4L]

对此:

Aggregate [sum(inc_val#6L) AS sum(inc(vals))#7L]
+- Project [inc(vals#4L) AS inc_val#6L]
   +- LocalRelation [vals#4L]

我有一些问题:

  1. 为什么他想要项目操作员?它有什么好处?
  2. 据我所知,Project 是表示 SELECT 语句的运算符,那么计划怎么可能不包含 Project 运算符?
4

1 回答 1

3

前提:聚合涉及两个步骤:

  1. 部分聚合的计算

  2. 其次是洗牌和全局聚合。

基本上聚合是一个两阶段的操作。

  1. Why did he want to have the Project operator? What is the advantage of it?
    我可以想到两种情况:
    启用代码生成:启用代码生成后,整个阶段的代码(包括 UDF 的代码)在单个迭代器中运行。当 UDF 是 CPU 密集型/内存密集型等时,这可能会导致内存问题。请注意,聚合发生在同一个迭代器中。
    Codegen disabled:在禁用 code-gen 的情况下,每个算子都将在自己的迭代器中运行。随着我们将聚合与 UDF 运行分离,OOM/CPU 变高的可能性降低了。
  2. As far as I know, Project is the operator that represents the SELECT statement, so how could possibly a plan not include a Project operator?
    只要最后一个运算符返回所需的列,我们就不需要显式项目。例如,假设最顶层的运算符(例如过滤器)返回 3 列。如果要求我们需要 3 列作为输出,则不需要显式项目。如果我们只需要三分之二,我们需要一个明确的项目。优化器规则将此作为查询计划的一部分。 https://github.com/apache/spark/blob/master/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/Optimizer.scala#L440
于 2020-02-03T09:54:06.710 回答