使用Spark Catalyst逻辑计划修改查询

时间:2018-09-12 17:17:56

标签: apache-spark apache-spark-sql

是否可以在其中添加/替换现有的列表达式 使用扩展点的DataFrame API / SQL。

例如:假设我们注入了可以检查项目的分辨率规则 计划中的节点,并检查“名称”列,将其替换 例如使用upper(name)。

使用扩展点是可能的。我有的例子 发现的大部分都是简单的,不会以我需要的方式操纵输入表达式。

请告诉我是否可行。

1 个答案:

答案 0 :(得分:1)

是的,这是可能的。

举个例子。假设我们要编写一条规则来检查Project运算符,并且该项目是否用于某个特定的列(例如“ column2”),然后将其乘以2。

import org.apache.spark.sql.catalyst.plans.logical._
import org.apache.spark.sql.catalyst.rules.Rule
import org.apache.spark.sql.catalyst.expressions._
import org.apache.spark.sql.catalyst.plans._
import org.apache.spark.sql.Column
import org.apache.spark.sql.types._

object DoubleColumn2OptimizationRule extends Rule[LogicalPlan] {
    def apply(plan: LogicalPlan): LogicalPlan = plan transform {
        case p: Project =>
          if (p.projectList.filter(_.name == "column2").size >= 1) {
              val newList = p.projectList.map { case x =>
                if (x.name == "column2") {
                  Alias(Multiply(Literal(2, IntegerType), x), "column2_doubled")()
                } else {
                  x
                }
              }
              p.copy(projectList = newList)
          } else {
              p
          }
    }
}

假设我们有一个表“ table1”,它有两列-column1,column2。

没有此规则-

> spark.sql("select column2 from table1 limit 10").collect()
Array([1], [2], [3], [4], [5], [6], [7], [8], [9], [10])

符合此规则-

> spark.experimental.extraOptimizations =  Seq(DoubleColumn2OptimizationRule)
> spark.sql("select column2 from table1 limit 10").collect()
Array([2], [4], [6], [8], [10], [12], [14], [16], [18], [20])

您还可以致电DataFrame上的explain检查计划-

> spark.sql("select column2 from table1 limit 10").explain
== Physical Plan ==
CollectLimit 10
+- *(1) LocalLimit 10
   +- *(1) Project [(2 * column2#213) AS column2_doubled#214]
      +- HiveTableScan [column2#213], HiveTableRelation `default`.`table1`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, [column1#212, column2#213]