hive源码

1 HQL 是如何转换为 MR 任务的

1.1 Hive 的核心组成介绍

hive源码_第1张图片

1)用户接口:Client

​ CLI(command-line interface)、JDBC/ODBC(jdbc 访问 hive)、WEBUI(浏览器访问 hive)

​ CLI:bin/hive 启动的客户端

​ JDBC:通过hiveserver2 jdbc方式连接的客户端

2)元数据:Metastore

​ 元数据包括:表名、表所属的数据库(默认是 default)、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等;

​ 默认存储在自带的 derby 数据库中,推荐使用 MySQL 存储 Metastore

3)Hadoop

​ 使用 HDFS 进行存储,使用 MapReduce 进行计算。

4)驱动器:Driver

​ 连接客户端和服务端的桥梁

5)解析器(SQL Parser)

​ 将 SQL 字符串转换成抽象语法树 AST,这一步一般都用第三方工具库完成,比如 antlr;

​ 对 AST 进行语法分析,比如表是否存在、字段是否存在、SQL 语义是否有误。

6)编译器(Physical Plan)

​ 将 AST 编译生成逻辑执行计划。

7)优化器(Query Optimizer)

​ 对逻辑执行计划进行优化。

8)执行器(Execution)

​ 把逻辑执行计划转换成可以运行的物理计划。对于 Hive 来说,就是 MR/Spark。

1.2 HQL 转换为 MR 任务流程说明

HQL编译为MR任务流程介绍

hive源码_第2张图片

2 HQL 转换为 MR 源码详细解读

2.1 HQL 转换为 MR 源码整体流程介绍

HQL转换为MR的核心流程

hive源码_第3张图片

2.2 程序入口 — CliDriver

​ 众所周知,我们执行一个 HQL 语句通常有以下几种方式:

​ 1)$HIVE_HOME/bin/hive 进入客户端,然后执行 HQL;

​ 2)$HIVE_HOME/bin/hive -e “hql”;

​ 3)$HIVE_HOME/bin/hive -f hive.sql; 执行sql文件

​ 4)先开启 hivesever2 服务端,然后通过 JDBC 方式连接远程提交 HQL。

​ 可 以 知 道 我 们 执 行 HQL 主 要 依 赖 于 H I V E H O M E / b i n / h i v e 和 HIVE_HOME/bin/hive 和 HIVEHOME/bin/hiveHIVE_HOME/bin/hivesever2 两种脚本来实现提交 HQL,而在这两个脚本中,最终启动的 JAVA 程序的主类为“org.apache.hadoop.hive.cli.CliDriver”,所以其实 Hive 程序的入口就是“CliDriver”这个类。

文字总结

从主方法进入 进入run方法

解析系统参数,定义标准输入输出流,解析用户参数

执行executeDriver方法


executeDriver方法中 里面有判断执行程序引擎是否mr或者spark 和ez

然后初始化控制台阅读器,按行读取控制台输入语句,不断追加到已读数据后面 ,识别到分号结尾将读取内容放入到解析processLine方法中(通过输入流读取一行一行的sql,直到读到以分号结尾的语句他就会调用processLIne方法)


在processLine方法中会按照;切分读进来的数据(因为一行可能有多个;)放入集合中,然后取出集合中的命令放入processCmd方法中

调用processCmd方法,对一行一行的命令做解析
processCmd中把输入语句分为4种类型
1.退出类型(quit,exit),2.以source开头执行sql文件,3.以!开头执行shell,4.执行hql语句


第4种类型执行hql语句 核心的是processLocalCmd方法
其中有获取开始时间,HQL核心run方法,获取结束时间,打印头信息,打印结果 等

run方法传入的是sql语句run(String command) run方法调用的是重载的run(String command,boolean alreadyCompiled)方法


run方法中调用runInternal方法

进入runInternal(command,alreadyCompiled)中有2个核心方法 1.编译HQL语句compiledInternal(),2.执行execute

1.编译HQL语句中包含解析器 编译器 优化器 2.执行方法中只包含执行器


runInternal方法中调用compiledInternal

compiledInternal方法中有一个compile方法

compile方法中

#tree = ParseUtils.parse(command, ctx)生成抽象语法树方法

#sem.analyze(tree, ctx);编译器和优化器工作


进入parse解析器方法中(parseUtils类)

调用重载的parse方法

new了一个parseDriver(解析驱动),调用parse(parseDriver类)方法解析命令返回抽象语法树

#parseDriver类的parse方法中

构建词法语法解析对象new hiveLexerX()对HQL做词法语法解析 将关键词替换成tokens,将解析之后的的tokens转化成解析器,解析器工作生成最终的抽象语法树


编译器

analyze 方法中调用了analyzeInternal方法 然后继续调用重载的analyzeInternal方法

处理AST转换为QueryBlock进一步转换为 OperatorTree;


优化器

创建了一个优化器,设置全局上下文(里面放的是优化策略),通过conf文件做初始化(优化通过遍历transformations整个优化器的集合做优化)


通过生成的taskTree做物理优化


runInternal方法中调用executor方法 执行器方法

根据任务树构建mrJob 然后执行任务launchTask

化通过遍历transformations整个优化器的集合做优化)


通过生成的taskTree做物理优化


runInternal方法中调用executor方法 执行器方法

根据任务树构建mrJob 然后执行任务launchTask

你可能感兴趣的:(hive,big,data,spark)