# week8-homework **Repository Path**: zero-night-01/week8-homework ## Basic Information - **Project Name**: week8-homework - **Description**: No description available - **Primary Language**: Scala - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-04-23 - **Last Updated**: 2022-05-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # week8-homework #### 作业说明 作业一 > 为 Spark SQL 添加一条自定义命令
> - SHOW VERSION;
> - 显示当前 Spark 版本和 Java 版本。 说明:需要下载 Spark 源码,此处以如下版本为例: - Spark 3.2.1 - Scala 2.12 - Java 8 首先需要将 `SHOW VERSION` 注册为 `statement`,将 `VERSION` 注册为关键字,并绑定用户输入。 操作:在下载的源码中,找到 `sql/catalyst/src/main/antlr4/org/apache/spark/sql/catalyst/parser/SqlBase.g4` 并新增如下内容 ```antlrv4 statement : query | SHOW VERSION #showVersion ansiNonReserved | VERSION nonReserved | VERSION //--SPARK-KEYWORD-LIST-START VERSION : 'VERSION'; ``` 接着在`spark-3.2.1` 根目录下运行命令: ```shell build/mvn antlr4:antlr4 -f pom.xml ``` 生成需要用到的上下文类等内容 接着实现对应的 `visit` 方法,如下: 在 `sql/core/src/main/scala/org/apache/spark/sql/execution/SparkSqlParser.scala` 中新增如下代码 ```scala class SparkSqlAstBuilder extends AstBuilder { ... override def visitShowVersion(ctx: ShowVersionContext): LogicalPlan = withOrigin(ctx) { ShowVersionCommand() } ... } ``` 在任意能访问到的地方创建 `ShowVersionCommand`,如下: ```scala case class ShowVersionCommand() extends LeafRunnableCommand { override val output: Seq[Attribute] = Seq(AttributeReference("version", StringType)()) override def run(sparkSession: SparkSession): Seq[Row] = { val sparkVersion = sparkSession.version val javaVersion = System.getProperty("java.version") val outputString = "spark version: %s, java version: %s".format(sparkVersion, javaVersion) Seq(Row(outputString)) } } ``` 完成后进行编译: ```shell build/mvn clean package -DskipTests -Phive -Phive-thriftserver ``` 成功后进入项目内的 `SparkSQL`: ```shell bin/spark-sql ``` 验证功能: ```shell spark-sql> show version; spark version: 3.2.1, java version: 1.8.0_332 Time taken: 1.404 seconds, Fetched 1 row(s) spark-sql> ``` 作业二 准备工作 ```sparksql set spark.sql.planChangeLog.level=WARN; ``` 题目一 ```sparksql CREATE TABLE sales ( id int, customerId int, amountPaid double ); EXPLAIN SELECT a.customerId FROM ( SELECT customerId, amountPaid as amount FROM sales WHERE amountPaid > 100.0 AND 1 = '1' ) a WHERE a.customerId < 20; ``` 日志片段 ```shell === Applying Rule org.apache.spark.sql.catalyst.optimizer.PushDownPredicates === Project [customerId#618] Project [customerId#618] !+- Filter (customerId#618 < 20) +- Project [customerId#618, amountPaid#619 AS amount#611] ! +- Project [customerId#618, amountPaid#619 AS amount#611] +- Filter (((amountPaid#619 > cast(100.0 as double)) AND (1 = cast(1 as int))) AND (customerId#618 < 20)) ! +- Filter ((amountPaid#619 > cast(100.0 as double)) AND (1 = cast(1 as int))) +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#617, customerId#618, amountPaid#619], Partition Cols: []] ! +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#617, customerId#618, amountPaid#619], Partition Cols: []] 22/05/02 17:16:58 WARN PlanChangeLogger: === Applying Rule org.apache.spark.sql.catalyst.optimizer.CollapseProject === Project [customerId#618] Project [customerId#618] !+- Project [customerId#618] +- Filter (((amountPaid#619 > cast(100.0 as double)) AND (1 = cast(1 as int))) AND (customerId#618 < 20)) ! +- Filter (((amountPaid#619 > cast(100.0 as double)) AND (1 = cast(1 as int))) AND (customerId#618 < 20)) +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#617, customerId#618, amountPaid#619], Partition Cols: []] ! +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#617, customerId#618, amountPaid#619], Partition Cols: []] 22/05/02 17:16:58 WARN PlanChangeLogger: === Applying Rule org.apache.spark.sql.catalyst.optimizer.BooleanSimplification === Project [customerId#618] Project [customerId#618] !+- Filter (((amountPaid#619 > 100.0) AND true) AND (customerId#618 < 20)) +- Filter ((amountPaid#619 > 100.0) AND (customerId#618 < 20)) +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#617, customerId#618, amountPaid#619], Partition Cols: []] +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#617, customerId#618, amountPaid#619], Partition Cols: []] ``` 注:Spark 3.0+ 中 PushDownPredicates 实现使用了 CombineFilters 题目二 ```sparksql EXPLAIN SELECT DISTINCT a.customerId FROM ( SELECT customerId, amountPaid as amount, 1.0 x, 'abc' y, Now() z FROM sales WHERE amountPaid > 100.0 AND 1 = '1' ORDER BY x, y, 3 ) a WHERE a.customerId < 20 EXCEPT SELECT customerId FROM sales; ``` 日志片段 ```shell === Applying Rule org.apache.spark.sql.catalyst.optimizer.ReplaceExceptWithAntiJoin === !Except false Distinct !:- Distinct +- Join LeftAnti, (customerId#663 <=> customerId#666) !: +- Project [customerId#663] :- Distinct !: +- Filter (customerId#663 < 20) : +- Project [customerId#663] !: +- Sort [x#654 ASC NULLS FIRST, y#655 ASC NULLS FIRST, x#654 ASC NULLS FIRST], true : +- Filter (customerId#663 < 20) !: +- Project [customerId#663, amountPaid#664 AS amount#653, 1.0 AS x#654, abc AS y#655, 2022-05-02 17:32:56.606 AS z#656] : +- Sort [x#654 ASC NULLS FIRST, y#655 ASC NULLS FIRST, x#654 ASC NULLS FIRST], true !: +- Filter ((amountPaid#664 > cast(100.0 as double)) AND (1 = cast(1 as int))) : +- Project [customerId#663, amountPaid#664 AS amount#653, 1.0 AS x#654, abc AS y#655, 2022-05-02 17:32:56.606 AS z#656] !: +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#662, customerId#663, amountPaid#664], Partition Cols: []] : +- Filter ((amountPaid#664 > cast(100.0 as double)) AND (1 = cast(1 as int))) !+- Project [customerId#666] : +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#662, customerId#663, amountPaid#664], Partition Cols: []] ! +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#665, customerId#666, amountPaid#667], Partition Cols: []] +- Project [customerId#666] ! +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#665, customerId#666, amountPaid#667], Partition Cols: []] 22/05/02 17:32:56 WARN PlanChangeLogger: === Applying Rule org.apache.spark.sql.catalyst.optimizer.ReplaceDistinctWithAggregate === !Distinct Aggregate [customerId#663], [customerId#663] +- Join LeftAnti, (customerId#663 <=> customerId#666) +- Join LeftAnti, (customerId#663 <=> customerId#666) ! :- Distinct :- Aggregate [customerId#663], [customerId#663] : +- Project [customerId#663] : +- Project [customerId#663] : +- Filter (customerId#663 < 20) : +- Filter (customerId#663 < 20) : +- Sort [x#654 ASC NULLS FIRST, y#655 ASC NULLS FIRST, x#654 ASC NULLS FIRST], true : +- Sort [x#654 ASC NULLS FIRST, y#655 ASC NULLS FIRST, x#654 ASC NULLS FIRST], true : +- Project [customerId#663, amountPaid#664 AS amount#653, 1.0 AS x#654, abc AS y#655, 2022-05-02 17:32:56.606 AS z#656] : +- Project [customerId#663, amountPaid#664 AS amount#653, 1.0 AS x#654, abc AS y#655, 2022-05-02 17:32:56.606 AS z#656] : +- Filter ((amountPaid#664 > cast(100.0 as double)) AND (1 = cast(1 as int))) : +- Filter ((amountPaid#664 > cast(100.0 as double)) AND (1 = cast(1 as int))) : +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#662, customerId#663, amountPaid#664], Partition Cols: []] : +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#662, customerId#663, amountPaid#664], Partition Cols: []] +- Project [customerId#666] +- Project [customerId#666] +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#665, customerId#666, amountPaid#667], Partition Cols: []] +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#665, customerId#666, amountPaid#667], Partition Cols: []] === Applying Rule org.apache.spark.sql.catalyst.optimizer.PushDownPredicates === Aggregate [customerId#663], [customerId#663] Aggregate [customerId#663], [customerId#663] +- Join LeftAnti, (customerId#663 <=> customerId#666) +- Join LeftAnti, (customerId#663 <=> customerId#666) :- Aggregate [customerId#663], [customerId#663] :- Aggregate [customerId#663], [customerId#663] : +- Project [customerId#663] : +- Project [customerId#663] ! : +- Filter (customerId#663 < 20) : +- Sort [x#654 ASC NULLS FIRST, y#655 ASC NULLS FIRST, x#654 ASC NULLS FIRST], true ! : +- Sort [x#654 ASC NULLS FIRST, y#655 ASC NULLS FIRST, x#654 ASC NULLS FIRST], true : +- Project [customerId#663, amountPaid#664 AS amount#653, 1.0 AS x#654, abc AS y#655, 2022-05-02 17:32:56.606 AS z#656] ! : +- Project [customerId#663, amountPaid#664 AS amount#653, 1.0 AS x#654, abc AS y#655, 2022-05-02 17:32:56.606 AS z#656] : +- Filter (((amountPaid#664 > cast(100.0 as double)) AND (1 = cast(1 as int))) AND (customerId#663 < 20)) ! : +- Filter ((amountPaid#664 > cast(100.0 as double)) AND (1 = cast(1 as int))) : +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#662, customerId#663, amountPaid#664], Partition Cols: []] ! : +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#662, customerId#663, amountPaid#664], Partition Cols: []] +- Project [customerId#666] ! +- Project [customerId#666] +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#665, customerId#666, amountPaid#667], Partition Cols: []] ! +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#665, customerId#666, amountPaid#667], Partition Cols: []] 22/05/02 17:32:56 WARN PlanChangeLogger: === Applying Rule org.apache.spark.sql.catalyst.optimizer.FoldablePropagation === Aggregate [customerId#663], [customerId#663] Aggregate [customerId#663], [customerId#663] +- Join LeftAnti, (customerId#663 <=> customerId#666) +- Join LeftAnti, (customerId#663 <=> customerId#666) :- Aggregate [customerId#663], [customerId#663] :- Aggregate [customerId#663], [customerId#663] : +- Project [customerId#663] : +- Project [customerId#663] ! : +- Sort [x#654 ASC NULLS FIRST, y#655 ASC NULLS FIRST, x#654 ASC NULLS FIRST], true : +- Sort [1.0 ASC NULLS FIRST, abc ASC NULLS FIRST, 1.0 ASC NULLS FIRST], true : +- Project [customerId#663, 1.0 AS x#654, abc AS y#655] : +- Project [customerId#663, 1.0 AS x#654, abc AS y#655] : +- Filter (((amountPaid#664 > cast(100.0 as double)) AND (1 = cast(1 as int))) AND (customerId#663 < 20)) : +- Filter (((amountPaid#664 > cast(100.0 as double)) AND (1 = cast(1 as int))) AND (customerId#663 < 20)) : +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#662, customerId#663, amountPaid#664], Partition Cols: []] : +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#662, customerId#663, amountPaid#664], Partition Cols: []] +- Project [customerId#666] +- Project [customerId#666] +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#665, customerId#666, amountPaid#667], Partition Cols: []] +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#665, customerId#666, amountPaid#667], Partition Cols: []] 22/05/02 17:32:56 WARN PlanChangeLogger: === Applying Rule org.apache.spark.sql.catalyst.optimizer.ConstantFolding === Aggregate [customerId#663], [customerId#663] Aggregate [customerId#663], [customerId#663] +- Join LeftAnti, (customerId#663 <=> customerId#666) +- Join LeftAnti, (customerId#663 <=> customerId#666) :- Aggregate [customerId#663], [customerId#663] :- Aggregate [customerId#663], [customerId#663] : +- Project [customerId#663] : +- Project [customerId#663] : +- Sort [1.0 ASC NULLS FIRST, abc ASC NULLS FIRST, 1.0 ASC NULLS FIRST], true : +- Sort [1.0 ASC NULLS FIRST, abc ASC NULLS FIRST, 1.0 ASC NULLS FIRST], true : +- Project [customerId#663, 1.0 AS x#654, abc AS y#655] : +- Project [customerId#663, 1.0 AS x#654, abc AS y#655] ! : +- Filter (((amountPaid#664 > cast(100.0 as double)) AND (1 = cast(1 as int))) AND (customerId#663 < 20)) : +- Filter (((amountPaid#664 > 100.0) AND true) AND (customerId#663 < 20)) : +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#662, customerId#663, amountPaid#664], Partition Cols: []] : +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#662, customerId#663, amountPaid#664], Partition Cols: []] +- Project [customerId#666] +- Project [customerId#666] +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#665, customerId#666, amountPaid#667], Partition Cols: []] +- HiveTableRelation [`default`.`sales`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, Data Cols: [id#665, customerId#666, amountPaid#667], Partition Cols: []] ``` 作业三 别名重命名示例 ```scala case class RenameAlias(spark: SparkSession) extends Rule[LogicalPlan] { override def apply(plan: LogicalPlan): LogicalPlan = { logInfo("In RenameAlias") plan transformAllExpressions { case e @ Alias(_, name) if name.startsWith("rename") => { logInfo("RenameAlias applied") e.withName(s"my_${e.name}") } } } } class MySparkSessionExtension extends (SparkSessionExtensions => Unit) { override def apply(extensions: SparkSessionExtensions): Unit = { extensions.injectResolutionRule { session => RenameAlias(session) } } } ``` `maven`打包后运行`spark-sql` ```shell bin/spark-sql --jars week8-homework-1.0-SNAPSHOT.jar --conf spark.sql.extensions=org.geektime.time.exercise3.MySparkSessionExtension ``` 执行如下查询验证结果: ```sparksql set spark.sql.planChangeLog.level=WARN; explain select 1 as rename_name; ``` 日志片段 ```shell === Applying Rule org.geektime.time.exercise3.RenameAlias === !Project [1 AS rename_name#10] Project [1 AS my_rename_name#10] +- OneRowRelation +- OneRowRelation ```