挖挖Hive的代码(二)——生成MapReduce(上)
来源:互联网 发布:手机数据库查看器 编辑:程序博客网 时间:2024/05/16 00:26
Hive在做完语义分析后,会把查询语句的逻辑转化成一个由operator构成的DAG。但是这个DAG不能完全对应于Hadoop的计算框架,还需要根据Hadoop的框架要求,进一步的切割剪裁才行,就是封装成对应的Task对象。
切割这个DAG的逻辑在SemanticAnalyse.java中的genMapRedTasks方法里,核心代码如下:
Map<Rule, NodeProcessor> opRules = new LinkedHashMap<Rule, NodeProcessor>(); opRules.put(new RuleRegExp(new String("R1"), "TS%"), new GenMRTableScan1()); opRules.put(new RuleRegExp(new String("R2"), "TS%.*RS%"), new GenMRRedSink1()); opRules.put(new RuleRegExp(new String("R3"), "RS%.*RS%"), new GenMRRedSink2()); opRules.put(new RuleRegExp(new String("R4"), "FS%"), new GenMRFileSink1()); opRules.put(new RuleRegExp(new String("R5"), "UNION%"), new GenMRUnion1()); opRules.put(new RuleRegExp(new String("R6"), "UNION%.*RS%"), new GenMRRedSink3()); opRules.put(new RuleRegExp(new String("R6"), "MAPJOIN%.*RS%"), new GenMRRedSink4()); opRules.put(new RuleRegExp(new String("R7"), "TS%.*MAPJOIN%"), MapJoinFactory.getTableScanMapJoin()); opRules.put(new RuleRegExp(new String("R8"), "RS%.*MAPJOIN%"), MapJoinFactory.getReduceSinkMapJoin()); opRules.put(new RuleRegExp(new String("R9"), "UNION%.*MAPJOIN%"), MapJoinFactory.getUnionMapJoin()); opRules.put(new RuleRegExp(new String("R10"), "MAPJOIN%.*MAPJOIN%"), MapJoinFactory.getMapJoinMapJoin()); opRules.put(new RuleRegExp(new String("R11"), "MAPJOIN%SEL%"), MapJoinFactory.getMapJoin());
如上代码所示,每一个规则会对应一个处理程序,例如遍历程序发现满足R5规则时,就会触发GenMRUnion1类的实现来处理。下面具体说说各个规则都干了什么。
R1:遇到TS(TableScanOperator)的时候,会进入GenMRTableScan1类的逻辑。它的逻辑很简单,就是创建一个新的plan(MapredWork对象),并将其包成相应的Task。如果是当前query是一条analyze指令,则会紧跟着刚才创建的task,新建一个StatsWork,当然这个plan也会被包成对应的Task。
R2:遇到当前解析队列的头一个operator是TS,而当前是RS(例如:
TS(1)-SEL(2)-RS(3))这样的情形时,会调用GenMRRedSink1类的实现来处理。它的核心逻辑如下:
if (opMapTask == null) { if (currPlan.getReducer() == null) { GenMapRedUtils.initPlan(op, ctx); } else { GenMapRedUtils.splitPlan(op, ctx); } } else { GenMapRedUtils.joinPlan(op, null, opMapTask, ctx, -1, false, false, false); currTask = opMapTask; ctx.setCurrTask(currTask); }
跟着if-else的逻辑来看:
如果当前RS的子operator没有绑定task,且当前task没有设置reducer的时候,那么会将这个RS的子operator设为当前task的reducer。
如果当前task(暂时称父task)已经有reducer了,那么不好意思,当前RS的子operator(reducer逻辑)只能放到一个新的task(暂时称子task)里去完成了,所以这个splitPlan方法会生成一个新的plan,并生成一个临时文件信息,通过这个临时文件将父task中的处理结果传递到子task中,由当前RS的子operator(新plan中的reducer)继续执行。这里还需要将当前RS(在父task中)替换为FS,而这个RS会被移到新创建的plan的map部分,当然它不能以top operator的形式出现,所以还会为它创建一个父operator——TS。例如遇到这样的DAG:
TS(1)-SEL(2)-GBY(3)-RS(4)-GBY(8)... \SEL(5)-GBY(6)-RS(7)-GBY(9)...那么会分割成两个task:
task1: task2: Map: TS(1)-SEL(2)-GBY(3)-RS(4) Map: TS(11)-RS(7) \SEL(5)-GBY(6)-FS(10) Red: GBY(8)... Red: GBY(9)...
如果是join情况,当前RS的子operator可能已经有对应的task信息了(它已经在join的另一路中被遍历过了),所以此刻会将当前的plan与RS的子operator对应的plan相合并,并将当前plan及task对象抛弃。
R3:遇到当前解析队列出现两个RS时(例如:
TS(1)-SEL(2)-GBY(3)-RS(4)-GBY(5)-SEL(6)-RS(7)),会调用GenMRRedSink2类的实现来处理。它的核心逻辑如下所示:
if (opMapTask == null) { GenMapRedUtils.splitPlan(op, ctx); } else { GenMapRedUtils.joinPlan(op, currTask, opMapTask, ctx, -1, true, false, false); currTask = opMapTask; ctx.setCurrTask(currTask); }
一段与R2规则类似的逻辑:
如果当前RS的子operator(reducer逻辑)没有对应的task信息,而当前RS已不是本次解析队列里的第一个遇到的RS了,此时可以断定当前plan对应的task必然已经有一个reducer了,所以当前这个RS的子operator必须变成一个新task的reducer。同R2规则里出现过的情况一样,调用GenMapRedUtils的splitPlan方法新建一个plan,通过临时文件作为媒介,将当前plan的处理结果传递到这个新建的plan中,用FS替换RS,转移RS到新的plan中,并创建相应的TS。
如果当前RS的子operator已经有对应的task信息了,joinPlan的逻辑会通过splitPlan方法为当前RS新建一个plan,并把这个新的plan与子operator对应的task合并为一个task。
R4:遍历operator遇到FS的时候,GenMRFileSink1的实现会通过该FS(FileSinkOperator)找到对应的MoveTask,并根据相关信息将MoveTask与当前Task关联起来。这个实现首先会判断当前FS是不是在做“insert overwrite”的操作,如果是,而且“hive.stats.autogather”开关设为了true,则会在FS对应的MoveTask后关联一个StatsTask(这个task是用来修改table或partition的metastore信息的,而MoveTask是用来处理数据的,分工不同)。接着,会通过“hive.merge.mapfiles”和“hive.merge.mapredfiles”开关来判断是否要在MoveTask之前添加合并数据的操作。合并数据的操作会添加一个MapRedTask来完成,至于这个task需不需要reducer就由hadoop的版本决定了:如果当前hadoop支持CombineHiveInputFormat(0.20以后是支持的),就不需要reducer了。完整的合并数据的操作是由一个关联了一个MoveTask和一个MapRedTask的ConditionalTask完成的,这个ConditionalTask会关联在FS所在的Task之后,而最初找到的MoveTask会分别关联到合并数据操作中新添加的MoveTask和MapRedTask之后。大致的关联关系如下:
/ MoveTask(1) -- MoveTask(0)MapRedTask -- ConditionalTask -- (FS) \ MapRedTask(merge) -- MoveTask(0)
R5:遍历operator遇到UNION时,会触发GenMRUnion1类的实现。这个实现的操作主要分两大类:Map-Only和Map-Reduce。
在Map-Only的情况下,通常只是简单的在交汇点UNION处切分开来,然后调整上下文信息,由其他规则去遍历解析:
TS(1)-SEL(2)-\ UNION(3)-SEL(4)-FS(5) ==> TS(1)-SEL(2)-UNION(3)-SEL(4)-FS(5)TS(6)-SEL(7)-/ TS(6)-SEL(7)-UNION(3)-SEL(4)-FS(5)如果是Map-Reduce的境况,例如:
TS(1)-SEL(2)-GBY(3)-RS(4)-GBY(5)-SEL(6)-\ UNION(7)-SEL(8)-FS(9) TS(10)-SEL(11)-GBY(12)-RS(13)-GBY(14)-SEL(15)-/就得类似R3规则那样先拆分再合并了,结果会如下所示:
---- stage1--\ stage2 stage3--/ ---- stage1: Map: TS(1)-SEL(2)-GBY(3)-RS(4) Red: GBY(5)-SEL(6)-FS1 stage3: Map: TS(10)-SEL(11)-GBY(12)-RS(13) Red: GBY(14)-SEL(15)-FS2 stage2: Map: UNION(7)-SEL(8)-FS(9)R6:遍历operator发现当前RS跟着UNION,会触发GenMRRedSink3类的实现。如果当前UNION所在Task是一个Map-Only的Task,很简单,直接调用R2规则的实现来处理;否则UNION之前的operator串应该已经被R5规则处理过了,而这里的处理方式就又和R2类似了,只是不再调用initPlan而是initUnionPlan方法。示例如下:
before: TS(1)-SEL(2)-GBY(3)-RS(4)-GBY(5)-SEL(6)-\ TS(7)-SEL(8)-GBY(9)-RS(10)-GBY(11)-SEL(12)--UNION(19)-SEL(20)-GBY(21)-RS(22)-GBY(23)-SEL(24)-FS(25) TS(13)-SEL(14)-GBY(15)-RS(16)-GBY(17)-SEL(18)-/
after: stage1-\ stage3--stage2 stage4-/ ---- stage1: Map: TS(1)-SEL(2)-GBY(3)-RS(4) Red: GBY(5)-SEL(6)-FS1 stage3: Map: TS(7)-SEL(8)-GBY(9)-RS(10) Red: GBY(11)-SEL(12)-FS2 stage4: Map: TS(13)-SEL(14)-GBY(15)-RS(16) Red: GBY(17)-SEL(18)-FS3 stage2: Map: UNION(19)-SEL(20)-GBY(21)-RS(22) Red: GBY(23)-SEL(24)-FS(25)待续……
- 挖挖Hive的代码(二)——生成MapReduce(上)
- 挖挖Hive的代码(三)——生成MapReduce(中)
- 挖挖Hive的代码(一)——UDF
- 挖挖Hive的代码(一)——UDF
- Mapr与Mapreduce的工作(二)——配置Mapreduce
- 详解Hive-CliDriver——细读Hive源码(二)
- hadoop初识之二:三大组件(HDFS,MapReduce,Yarn)以及mapreduce运行在yarn上的过程
- hive 操作(二)——使用 mysql 作为 hive 的metastore
- Hive查询在MapReduce上的执行过程
- E-MapReduce上Hive创建基于oss的外部表
- 【Hadoop】Hive官方文档翻译——Hive Tutorial(上)(Hive 入门指导)
- 代码自动生成(二)
- 使用Hive编写Mapreduce代码
- Hive用户接口(二)—使用Hive JDBC驱动连接Hive操作实例
- hadoop 中MapReduce代码运行在win7上(本地)
- 【转载】HDFS+MapReduce+Hive+HBase 十分钟快速入门(二)
- 二、 Hive语法树的生成
- MapReduce数据流(二)
- HDU/HDOJ 4043 BUPT 235 FXTZ II 2011ACM北京网络赛 D题
- C语言的函数指针的例子
- 链表排序
- 用汇编的眼光看C++(之模板类)
- 系统安全性之数字加密与数字签名
- 挖挖Hive的代码(二)——生成MapReduce(上)
- Hibernate构建一个CURD的程序
- 为什么有一些网站搜索不到啊
- Fedora 9中如何配置Samba来实现WINDOWS与LINUX之间的文件共享!
- HeadFirst设计模式学习笔记3-单件模式
- 简单工厂
- AS3数组
- 深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用
- Java异常处理笔记