Spark SQL执行计划到RDD全流程记录

记录Spark SQL生成执行计划的全流程和代码跟踪。Spark版本是2.3.2。上图流程描述了Spark SQL 怎么转成Spark计算框架可以执行的分布式模型,下面结合一个样例,跟踪每个步骤。
摘要由CSDN通过智能技术生成

目录

0、样例说明

1、解析词义,语义,生成语法树

1.1、概念

1.2、Spark源码分析

2、Unresolved Logical Plan

QueryExecution

3、Analyzed Logical Plan

源码

SessionCatalog

Analyzer Rule Batch

foldLeft和foldRight

对比

4、Optimized Logical Plan

5、Physical Plan

SparkPlan 

WholeStageCodegenExec


记录Spark SQL生成执行计划的全流程和代码跟踪。Spark版本是2.3.2。

 上图流程描述了Spark SQL 怎么转成Spark计算框架可以执行的分布式模型,下面结合一个样例,跟踪每个步骤。

0、样例说明

SQL样例:

select 
    t1.*,
    t2.id
from 
    test.tb_hive_test t1
join 
    test.test t2
on 
    t1.a == t2.name and imp_date == '20221216'

test.tb_hive_test是分区表,test.test是非分区表,两张表的建表语句:

CREATE TABLE test.tb_hive_test(
    a string, 
    b string
)
PARTITIONED BY (imp_date string COMMENT '分区时间')
Stored as ORC


CREATE TABLE test.test(
    id int, 
    name string,
    create_time timestamp
)
Stored as ORC

1、解析词义,语义,生成语法树

1.1、概念

SparK基于ANTLR语法解析SQL,ANTLR是可以根据输入自动生成语法树并可视化的显示出来的开源语法分析器。 ANTLR 主要包含词法分析器,语法分析器和树分析器。

  • 词法分析器又称 Scanner、Lexer 或 Tokenizer。词法分析器的工作是分析量化那些本来毫无意义的字符流, 抽取出一些单词,例如关键字(例如SELECT)、标识符(例如STRING)、符号(例如=)和操作符(例如UNION) 供语法分析器使用。
  • 语法分析器又称编译器。在分析字符流的时候,词法分析器只关注单个词语,不关注上下文。语法分析器则将收到的 Token 组织起来,并转换成为目标语言语法定义所允许的序列。
  • 树分析器可以用于对语法分析生成的抽象语法树进行遍历,并能执行一些相关的操作。

1.2、Spark源码分析

当提交上述SQL是,会调用该方法:

package org.apache.spark.sql

class SparkSession private(...){
    //sqlText为输入的SQL
    def sql(sqlText: String): DataFrame = {
        Dataset.ofRows(self, sessionState.sqlParser.parsePlan(sqlText))
      }
}

sessionState.sqlParser的parsePlan方法在AbstractSqlParser进行具体实现:

package org.apache.spark.sql.catalyst.parser


abstract class AbstractSqlParser extends ParserInterface with Logging {
    //1、parsePlan函数具体实现
    override def parsePlan(sqlText: String): LogicalPlan = parse(sqlText) { parser =>
        
        astBuilder.visitSingleStatement(parser.singleStatement()) match {
          case plan: LogicalPlan => plan
          case _ =>
            val position = Origin(None, None)
            throw new ParseException(Option(sqlText), "Unsupported SQL statement", position, position)
        }
    }


    //2、调用parse方法
    protected def parse[T](command: String)(toResult: SqlBaseParser => T): T = {
        logDebug(s"Parsing command: $command")
        //词法分析器
        val lexer = new SqlBaseLexer(new UpperCaseCharStream(CharStreams.fromString(command)))
        lexer.removeErrorListeners()
        lexer.addErrorListener(ParseErrorListener)

      
        val tokenStream = new CommonTokenStream(lexer)
        val parser = new SqlBaseParser(tokenStream)  //语法分析器
        parser.addParseListener(PostProcessor)
        parser.removeErrorListeners()
        parser.addErrorListener(ParseErrorListener)
        ...
    }
}

debug可以看到,执行到这里,sql被拆解成了很多类型的**Context

这些Context类都是根据ANTLR语法去解析SqlBase.g4这个DSL脚本,然后生成的,比如下面这个querySpecification就会生成QuerySpecificationContext类,里面就能通过各类参数记录下Select开头的某类SQL的词义和值。

 把SQL解析成AST语法树之后,就可以开始构建逻辑执行计划。

2、Unresolved Logical Plan

回到上面得parsePlan函数,第一步生成语法树之后,第二步是使用 AstBuilder (树遍历)将语法

树转换成 LogicalPlan。这个 LogicalPlan 也被称为 Unresolved LogicalPlan。

package org.apache.spark.sql.catalyst.parser


abstract class AbstractSqlParser extends ParserInterface with Logging {
    //1、parsePlan具体实现
    override def parsePlan(sqlText: String): LogicalPlan = parse(sqlText) { parser =>
        //2、astBuilder遍历语法树,获得Unresolved LoginPlan
        astBuilder.visitSingleStatement(parser.singleStatement()) match {
          case plan: LogicalPlan => plan
          case _ =>
            val position = Origin(None, None)
            throw new ParseException(Option(sqlText), "Unsupported SQL statement", position, position)
        }
    }
}

从代码上看,第二步执行完成后,应该得到的是如下的执行计划,所有的表和字段,都没有关联到实际的表和元数据,只是简单的做一步SQL的解析,生成语法树。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spark SQLSpark RDD是Apache Spark中两种不同数据处理模块,它们有一些不同的特点和优势。 Spark RDD(弹性分布式数据集)是Spark最早引入的核心数据结构,它是一个分布式的、不可变的弹性数据集合。RDD提供了一种高度可扩展的数据处理模型,可以在内存中高效地处理大规模数据集。RDD具有以下优势: 1. 灵活性:RDD提供了丰富的转换操作和行动操作,可以进行复杂的数据处理和分析。它支持函数式编程风格,可以通过链式调用多个转换操作来构建复杂的数据处理流程。 2. 容错性:RDD具有容错机制,可以自动恢复失败的任务,并且可以在节点故障时重新计算丢失的数据。这使得RDD非常适合处理大规模数据集时的容错需求。 3. 内存管理:RDD可以将数据存储在内存中,以提高数据处理速度。同时,RDD还支持磁盘持久化,可以将数据持久化到磁盘上,以便在内存不足时仍然能够高效地处理大规模数据。 Spark SQLSpark中用于处理结构化数据的模块,它提供了一种更高级别的API和查询语言,使得开发者可以使用SQL语句来查询和分析数据。Spark SQL具有以下优势: 1. 性能优化:Spark SQL使用Catalyst优化器来对SQL查询进行优化,可以自动推断查询计划并进行优化,以提高查询性能。此外,Spark SQL还支持将数据存储在列式存储格式中,以进一步提高查询性能。 2. 数据集成:Spark SQL可以与各种数据源进行集成,包括Hive、HBase、Parquet等。这使得开发者可以方便地在Spark中处理不同类型的数据。 3. 数据格式支持:Spark SQL支持多种数据格式,包括JSON、CSV、Avro等。这使得开发者可以方便地处理不同格式的数据。 综上所述,Spark RDD适用于需要灵活性和容错性的复杂数据处理场景,而Spark SQL适用于需要高性能查询和结构化数据处理的场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值