Hive源码阅读-3-hive启动

当我们在终端中输入hive时,会执行位于$HIVE_HOME/bin/hive的一个脚本,这个脚本又会执行bin下面的ext目录中的每个sh脚本。在ext目录下面包含了很多脚本,用于启动各种Hive所依赖的服务。 这些脚本中cli.sh是我们关注的入口,中cli.sh中会调用hadoop jar命令,启动”org.apache.hadoop.hive.cli.CliDriver”。 CliDriver的第620行是main函数,在这里实例化CliDriver并调用run方法。 在CliDriver的构造函数中,会获得SessionState实例。SessionState封装了与会话相关的公共数据。SessionState同样为线程静态会话对象提供支持,这样就可以在代码的任何地方访问Session,并且能够获得配置信息。 每个线程都与SessionStates相关联,SessionStates包含SessionState与HiveConf实例。 SessionStates实例化后,state与conf变量都为空。当CliDriver调用ss.get方法获取一个与线程关联的SessionStates,会得到空的state变量。CliDriver发现state为空,会创建Configuration实例。 当CliDriver实例化完成后,会执行run方法。在run方法中实例化OptionsProcessor、初始化Log4j、创建CliSessionState。其中CliSessionState继承自SessionState,CliSessionState添加了database、execString、filename等属性。 在创建CliSessionState时,需要传递HiveConf实例。HiveConf继承自hadoop的Configuration类。HiveConf的构造函数需要SessionState.class来获取hiveJar路径(“apache-hive-1.2.1-bin/lib/hive-exec-1.2.1.jar”)。 当CliSessionState实例化完成后,将该实例传递给SessionState.start来启动session。Session启动时,首先将CliSessionState关联到该线程当SessionStates当state变量上. 然后调用getMSC获取SessionHiveMetaStoreClient实例。IMetaStoreClient接口包含获取数据库名、表名、分区信息等获取元数据等方法. 当Session启动后,CliDriver的executeDriver方法会被调用. 在这个方法中,还会初始化另一个CliDriver实例,接下来获取用户输入的SQL语句,将SQL语句传递给CliDriver的processLine处理. processLine方法将会把用户输入的SQL按照分号”;”拆分,每个SQL称为oneCmd. oneCmd可能是被‘\’修饰的换行SQL中其中的一行,所以需要拼接. 拼接的完整SQL存入command变量中,交给processCmd方法处理. 在processCmd方法中,获取CliSessionState实例,将即将被执行的command存入Session的lastCommand变量, 以保存上一条执行的SQL. command不光是SQL,也可能是exit、quit等命令, 还可能是一条由!开头的shell命令, 在这里我们只关注SQL. SQL将会继续交给processLocalCmd方法处理, processLocalCmd需要待执行的SQL-cmd、CommandProcessor – proc与CliSessionState – ss. 如果proc是Driver的实例, 那么就会把待执行的SQL交给org.apache.hadoop.hive.ql.Driver的run方法执行. 下图显示出了从CliDriver.main开始到Driver.run的调用栈. 本文分析了从键入hive命令开始,到接受待执行到SQL语句的过程. SQL语句的实际执行交由Driver的run方法负责, 下一章我们从分析Driver类开始.

Read more

Hive源码阅读-2-Hive设计

图1显示了Hive的主要部件以及与Hadoop交互的流程. Hive主要包括以下部件 UI – 用户用于提交查询以及操作Hive的的界面. Hive同时提供命令行与GUI Driver – 用于接受查询的组建. 这个组建实现了会话处理, 它基于JDBC/ODBC接口提供了执行与抽取的APIs. Compiler – 解析SQL, 对查询块和查询表达式做语义分析, 最终会产生执行计划. 查询计划附带了来自于metastore中表和分区信息的元数据. Metastore – 该组建存储了各个表与分区的结构信息, 如列名、列类型. Execution Engine – 该组建负责执行由编译器生成的执行计划. 该计划是由stage组成的DAG. 执行引擎负责管理不同阶段plan的依赖以及在相应的系统组件上执行这些计划. 图1显示了系统的执行流. 首先UI向Driver调用执行接口(1:executeQuery). Driver会为查询创建Session, 并且向Compiler发送查询来产生执行计划(2:getPlan). Compiler从Metastore获取必要的元数据(3:getMetaData, 4:sendMetaData). 元数据被用来校验查询树中表达式的类型, 也可能被用来根据查询谓词对分区进行剪枝. 查询计划由Compiler所生成(5:sendPlan), 它是一个包含stages的DAG, 每个stage是map或reduce操作, 也可以是对元数据的操作, 还可以是对HDFS对操作. 对于map/reduce类型的stages来说, 这类plan包含了map操作符树(在mapper端被执行的操作符树)以及reduce操作符树. 执行引擎将这些stages提交到系统相应的组件. 在每个任务(mapper/reducer)中, 与表关联的或与中间结果关联的反序列化器被用来从HDFS上读取行. 一旦产生出输出, 他们就会被序列化然后被当作临时文件写入HDFS(该操作在mapper端完成, 这是防止任务中不包含reduce操作). 之后的map/reduce操作会读取上一步产生的临时文件. 对于DML操作, 最终的临时文件被移动到保存表的路径. 产生临时文件并移动,而不是直接保存到最终路径. 这么做可以避免脏读的发生, 因为在HDFS中文件重命名是原子操作. 对于查询来说,…

Read more

Hive源码阅读-1-环境搭建

Hive版本与下载地址 项目编译 配置Hive 在Intellij IDEA中导入与调试项目 1. Hive版本与下载地址 http://archive.apache.org/dist/hive/hive-1.2.1/ 2. 项目编译 依赖:Apache Maven 3.6.0、JDK 1.8.0_144、Hadoop 2.X 打包命令:mvn clean package -Phadoop-2 -DskipTests -Pdist clean表示删除$HIVE_HOME/packaging/target目录 -Pdist表示使用pom.xml中名为dist的profile;-Phadoop-2表示支持hadoop 2;-DskipTests表示跳过测试。当命令执行完毕后,我们可以在“apache-hive-1.2.1-src/packaging/target/apache-hive-1.2.1-bin/apache-hive-1.2.1-bin”找到编译完成的完整的项目。为了能够正常使用编译好的Hive,我们对它进行相应的配置。 3. 配置Hive 为了能够中终端中使用hive命令,我们在.bashrc(Mac OS为.bash_profile文件)中追加 我们在conf/hive-site.xml中添加以下内容来配置metadata存贮的位置,下面的配置文件使用derby数据库存储metadata。mapreduce.framework.name变量表示,我们尽可能的使用local模式来执行SQL。 我们接下来修改hive-env.sh,中其中指定HADOOP_HOME与HIVE_CONF_DIR的位置 当上述配置修改完毕后,我们使用source ~/.bashrc命令使终端中的环境变量生效。接下来执行hive,创建新表来测试环境是否配置成功。 4. 在Intellij IDEA中导入与调试项目 点击File->Close关闭当前项目,接下来点击Import Project导入“apache-hive-1.2.1-src”。当导入完毕后,我们点击Idea右边的Maven,展开Profiles,勾选hadoop-2。 我们点击Run-Edit Configurations,中Templates中选择Remote。新建一个远程调试的Configuration。然后我们使用以下命令启动一个启用了远程调试的hive进程 接下来,点击刚刚中Idea中创建的远程Configuration,来连接到正在等待的hive。下面,我们就可以中Idea中下断点,对Hive进行单步调试与分析了。 参考: Hive源码编译及阅读修改调试 Hive Developer FAQ

Read more