大数据 - hive执行SQL语句基本流程- 源码02

Driver类

Driver类是hive最核心的类。Driver类是查询的起点,run()方法会先后调用compile()和execute()两个函数来完成查询,所以一个command的查询分为compile和execute两个阶段。

编译的过程


Compiler简介

  • 解析器(Parser)–将查询字符串转换为解析树表示形式。
  • 语义分析器(Semantic Analyser)-将解析树转换为内部查询表示形式,该表示形式基于块。
  • 逻辑计划生成器(Logical Plan Generator)将内部查询表示形式转换为逻辑计划,该逻辑计划由运算符树组成。但是reduceSink等运算符是Hive专用的,将该计划转换为一系列map-reduce作业。
  • 查询计划生成器(Query Plan Generator)将逻辑计划转换为一系列的map-reduce任务。 查询计划计划被序列化并写入文件。
代码入口以及过程

Driver.run()方法调用Driver.runInternal()方法,首先该方法中会判断SQL是否经过编译,若未进行编译,则会调用compileInternal之后调用compile方法进行编译。

利用antlr将HiveQL转换成抽象语法树(AST)。
  • 首先使用antlr工具将srcqlsrcjavaorgapachehadoophiveqlparsehive.g编译成以下几个文件:HiveParser.java, Hive.tokens, Hive__.g, HiveLexer.java。
  • HiveLexer.java和HiveParser.java分别是词法和语法分析类文件,Hive__.g是HiveLexer.java对应的词法分析规范,Hive.tokens定义了词法分析后所有的token。
  • 然后沿着“Driver.compile()->ParseDriver.parse(command, ctx)->HiveParserX.statement()->antlr中的API”这个调用关系把输入的HiveQL转化成ASTNode类型的语法树。HiveParserX是由antlr生成的HiveParser类的子类。
      //将SQL语句转化为AST树
      ParseDriver pd = new ParseDriver();
      ASTNode tree = pd.parse(command, ctx);
      tree = ParseUtils.findRootNonNullToken(tree);
      perfLogger.PerfLogEnd(CLASS_NAME, PerfLogger.PARSE);
利用对应的SemanticAnalyzer类,将AST树转换成Map-reduce task。

这部分会用到BaseSemanticAnalyzer.analyze,大致流程是先通过anticAnalyzerFactory.get(queryState, tree),初始化BaseSemanticAnalyzer对象,并且确定了该SQL的类型。SQL的类型以及使用了哪些算子都在org/apache/hadoop/hive/ql/parse/HiveParser.g语法文件中枚举出来了。
然后会通过sem.analyze(tree, ctx)调用analyzeInternal

  public void analyze(ASTNode ast, Context ctx) throws SemanticException {
    initCtx(ctx);
    init(true);
    analyzeInternal(ast);
  }

以查询语句为例。进入进入的子类是SemanticAnalyzer. analyzeInternal()
整体逻辑为:

  1. doPhase1():将sql语句中涉及到的各种信息存储起来,存到QB中去,留着后面用。
if (!doPhase1(child, qb, ctx_1, plannerCtx)) {
      // if phase1Result false return
      return false;
    }
  1. getMetaData():获取元数据信息,主要是sql中涉及到的 表 和 元数据 的关联
 public void getMetaData(QB qb, boolean enableMaterialization) throws SemanticException {
    try {
      if (enableMaterialization) {
        getMaterializationMetadata(qb);
      }
      getMetaData(qb, null);
    } catch (HiveException e) {
      // Has to use full name to make sure it does not conflict with
      // org.apache.commons.lang.StringUtils
      LOG.error(org.apache.hadoop.util.StringUtils.stringifyException(e));
      if (e instanceof SemanticException) {
        throw (SemanticException)e;
      }
      throw new SemanticException(e.getMessage(), e);
    }
  }
  1. genPlan():生成operator tree/DAG
Operator sinkOp = genOPTree(ast, plannerCtx);


Operator genOPTree(ASTNode ast, PlannerContext plannerCtx) throws SemanticException {
    return genPlan(qb);
  }


  private Operator genPlan(QB parent, QBExpr qbexpr) throws SemanticException {
    if (qbexpr.getOpcode() == QBExpr.Opcode.NULLOP) {
      boolean skipAmbiguityCheck = viewSelect == null && parent.isTopLevelSelectStarQuery();
      return genPlan(qbexpr.getQB(), skipAmbiguityCheck);
    }
    if (qbexpr.getOpcode() == QBExpr.Opcode.UNION) {
      Operator qbexpr1Ops = genPlan(parent, qbexpr.getQBExpr1());
      Operator qbexpr2Ops = genPlan(parent, qbexpr.getQBExpr2());

      return genUnionPlan(qbexpr.getAlias(), qbexpr.getQBExpr1().getAlias(),
          qbexpr1Ops, qbexpr.getQBExpr2().getAlias(), qbexpr2Ops);
    }
    return null;
  }
  1. optimize():优化,对operator tree/DAG 进行一些优化操作,例如列剪枝等(目前只能做rule-based optimize,不能做cost-based optimize)
  //逻辑优化
    pCtx = optm.optimize();//fetchTask在逻辑执行计划最后一步生成
  1. getFetchTask()开始生成物理执行计划
    //fetchTask是物理执行计划的开始
    FetchTask origFetchTask = pCtx.getFetchTask();

    //不同引擎生成不同物理计划
    compiler.compile(pCtx, rootTasks, inputs, outputs);


    //生成物理执行计划
    generateTaskTree(rootTasks, pCtx, mvTask, inputs, outputs);


    //物理优化
    optimizeTaskPlan(rootTasks, pCtx, ctx);

整体的编译流程大概如此,下篇谈一下执行的过程。
本文采用hive2.1.1源码为参考。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值