大数据 - 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: 在Linux环境中,可以使用Hive CLI来执行SQL语句,具体步骤如下:1. 首先,连接Hive服务器,使用命令:$Hive --service hiveserver。2. 然后,使用命令:$Hive -e 'SQL语句'来执行SQL语句。3. 最后,使用命令:$Hive -f '脚本文件'来执行脚本文件中的SQL语句。 ### 回答2: 在Linux环境下,我们可以通过Hive执行SQL语句。首先,我们需要确保已经在Linux系统上安装了Hadoop和Hive。 步骤如下: 1. 打开终端,在Linux命令行中输入`hive`命令,启动Hive Shell。 2. 在Hive Shell中,我们可以执行各种Hive命令和SQL语句。首先,我们需要创建数据库(如果还不存在)。使用`CREATE DATABASE`语句创建数据库,例如`CREATE DATABASE mydatabase;`。 3. 接下来,我们需要切换到刚创建的数据库。使用`USE`命令切换到指定数据库,例如`USE mydatabase;`。 4. 现在,我们可以执行任何SQL语句了。例如,我们可以使用`CREATE TABLE`语句创建表,使用`SELECT`语句查询数据,使用`INSERT INTO`语句插入数据等等。示例:`CREATE TABLE mytable (id INT, name STRING);`、`SELECT * FROM mytable;`、`INSERT INTO mytable VALUES (1, 'John');`。 5. 若需要退出Hive Shell,可以使用`QUIT`或`EXIT`命令。 另外,我们还可以通过将SQL语句保存在一个`.sql`文件中,然后在Hive Shell中执行该文件来批量执行SQL语句。使用`SOURCE`命令,例如`SOURCE /path/to/script.sql;`。 总之,在Linux环境中,可以通过Hive Shell来执行SQL语句,同时也可以将SQL语句保存在文件中进行批量执行。这样可以更灵活和高效地进行数据查询和处理。 ### 回答3: 要在Linux环境中通过Hive执行SQL语句,可以按照以下步骤进行操作: 1. 首先,确保已经在Linux环境中安装了Hive。可以通过在终端中输入命令`hive -version`验证是否安装成功。 2. 打开终端,使用命令`hive`来启动Hive的命令行界面。 3. 在Hive命令行界面中,可以直接输入SQL语句执行。例如,要执行创建表的SQL语句,可以输入类似以下的命令: ``` CREATE TABLE my_table ( id INT, name STRING ); ``` 4. 想要执行一个完整的SQL脚本文件,可以使用以下命令: ``` hive -f /path/to/sql_script.sql ``` 其中,`/path/to/sql_script.sql`是你的SQL脚本文件的路径。 5. 另外,还可以通过Hive命令行界面执行HiveQL查询。例如,要查询某个表的数据,可以使用以下命令: ``` SELECT * FROM my_table; ``` 6. 执行SQL语句后,Hive会返回相应的结果或者执行的状态信息。 7. 如果需要在脚本中使用变量,可以使用Hive的参数替换。例如,使用`${var}`的形式引用参数,并在执行脚本时使用`-d`选项指定参数的值。例如: ``` SET my_var=value; SELECT * FROM ${hiveconf:my_var}; ``` 总之,通过以上步骤,在Linux环境中可以很方便地使用Hive执行SQL语句

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值