TDW开发之HIVE篇
网友 data.qq.com

前言

        经过几年的发展,Hadoop已经成为大数据时代存储和处理海量数据的事实标准。它依靠MapReduce框架实现了计算能力的线性扩展。MapReduce是一个相当严格的编程模型,这意味着使用它完成分布式编程需要做的工作相当的少。即便如此,对于普通的数据分析人员来说,直接使用MapReduce的门槛仍然很高:首先,你需要对MapReduce框架有一定的了解,其次需要对计算过程进行建模,把它划分成几个有依赖关系的MapReduce Job,然后实现每一个MapReduce job,在这个过程中,你需要了解输入输出文件的格式,分区方法等等,有时甚至要自己处理数据倾斜的问题。

        HIVE的诞生将使用MapReduce门槛大大地降低了。Hive是建立在 Hadoop 上的数据仓库。它定义了简单的类 SQL 查询语言,称为 HQL,它允许熟悉 SQL 的用户查询数据。同时,这个语言也允许熟悉 MapReduce 开发者的开发自定义的 mapper 和 reducer 来处理内建的 mapper 和 reducer 无法完成的复杂的分析工作。

        TDW HIVE在社区0.3.1版本的HIVE基础上实现了一套兼容商业数据仓库功能的SQL语法,同时做了很多稳定性和性能上的优化。这使得习惯了商业数据仓库的用户不需要太大的学习成本就可以轻松的使用TDW。除此之外,TDW还提供了一套集成开发环境(TDW IDE)让用户可以很方便的完成SQL/PLSQL的开发和调试。

HIVE在TDW中所处的位置

blob.png

      HIVE是TDW核心系统的入口,外围系统TDBANK,TDWIDE和Lhotse等将产生的SQL提交给HIVE,HIVE将这些SQL进行一系列复杂处理,最终翻译成一组相互依赖的MapReduce任务。 HIVE本地有一个简单的调度程序,以一定的规则和次序将MapReduce任务依次提交给底层的MapReduce层。

        HIVE的重要性是不言而喻的,它对外提供的SQL语法和接口决定了系统的易用性,它生成的MapReduce执行计划也是决定SQL执行效率的主要因素之一。

HIVE VS RDBMS

        虽然HIVE提供类似传统关系型数据库类似的SQL语法和功能,但由于在系统架构和计算流程上的巨大差异导致两者在使用上还是存在一些差别。所以了解两者之间的差别是很有必要的,只有了解了HIVE的特点和优势所在,才能开发出对TDW尽量友好的程序,提升开发效率和SQL计算效率。HIVE比较适合以批处理的方式处理需要分析整个数据集的问题,而RDBMS适用于点查询或者数据集需要经常少量更新的场合。

blob.png

TDW HIVE SQL基本特征

        TDW早年的发展目标之一是取代公司的商业数据仓库,但原始的HIVE SQL无论从功能性还是从易用性上都与ORACLE相距甚远。为此TDW项目组对社区HIVE进行了大规模的改造,实现了一套兼容商业数据仓库功能的SQL语法:

        记录级和批量的INSERT/UPDATE/DELETE

        CREATE TABLE AS/ CREATE TABLE LIKE

        INNER JOIN, LEFT/RIGHT/FULL OUTER JOIN, SEMI JOIN, CROSS JOIN

         EXIST/NOT EXIST

        GROUP BY, CUBE, ROLLUP, GROUPIING SET

        DISTINCT/MULTIDISTINCT

        HAVING

        ORDER BY

        UNION/UNION ALL

        WITH:提供和ORACLE类似的WITH AS语法和功能

        丰富的UDF函数:各类用于处理时间,数值,字符串等对象的函数

        聚合函数:SUM/MAX/MIN/COUNT/WM_CONCAT

        分析函数(窗口函数)

        多种数据分区格式:LIST分区/RANGE分区/HASH分区

        数据挖掘和统计函数

        SQL/MED:与RDBMS(ORACLE,TPG)实现互联互通

        多种存储格式:文本/结构化/列存储/ProtoBuf/行列混合式存储(RCFIle)格式

        外表,视图

TDW SQL开发流程

        在了解了TDW SQL之后,就可以使用TDW IDE写SQL完成自己的数据分析了。TDW IDE是一个构建与eclipse平台之上的集成开发环境,它提供了一整套TDW SQL/PLSQL的开发,调试和运行环境。它提供的主要功能如下:

        SQL/PLSQL编辑:语法高亮,关键字和函数用法提示,自动补全,SQL格式化

        SQL调试:语法检查,低效SQL提示,SQL执行计划图形化展示

        SQL运行时管理:SQL运行进度展示,SQL任务终止

        SQL结果处理:历史结果集保存,导出为文件,编码和格式转换

        PLSQL调试:断点,单步调试等

        数据传输通道:数据导入/数据导出

        其他:SQL执行历史和SQL编辑文件管理,PLSQL脚本上传洛子等

使用TDW IDE开发的基本步骤:

1) 配置TDW DB连接信息

        TDW有严格的权限体系,所以使用TDW之前需要先申请自己需要使用的库和表的权限。有了权限之后就可以在IDE的连接配置部分配置连接信息了。

blob.png

2) 库表元数据浏览

        在配置完DB之后,双击DB图标既可以查看这个DB下的表,可以使用搜索功能在数形控件中查找待分析数据所在的表并查看它的列信息和分区信息等,如图3所示(元数据浏览视图)。

blob.png

3) SQL开发

        在了解了数据表的元数据信息后,就可以打开TDW IDE的SQL编辑器进行SQL的开发了。SQL编辑器提供了非常强大的编辑功能,让SQL开发事半功倍,如图3所示(SQL编辑窗口)。

4) SQL预编译和执行计划查看

        SQL编辑完成后,可以使用预编译功能查看SQL是否有语法错误,同时也可以查看SQL生成的执行计划,从中大致了解SQL需要扫描的数据量和计算步骤。SQL执行计划如图4所示。

blob.png

5) SQL提交和运行时信息查看

        在确认没有语法错误后,就可以运行SQL了。TDW IDE会使用一些简单的算法找出SQL中比较低效的部分并提示用户。SQL开始运行后,可以在IDE上查看SQL的执行进度,也可以通过IDE跳转到MapReduce Job的执行页面,查看Job的更详细的信息。当不需要SQL结果,或者发现SQL的逻辑不是自己想要的,可以使用IDE 的Kill按钮终止SQL的运行。SQL运行管理视图如图3所示。

6) SQL结果查看和处理

        当SQL运行完成后(进度达到100%,如果SQL长期处于获取结果状态,则说明SQL结果集过大,可以在SQL最后加上limit减少获取的结果集,缩短结果获取时间),可以查看SQL结果并选择将结果保存为本地文件。SQL结果展示窗口如图5所示。

blob.png

   如果只是需要简单的跑一些临时分析任务,上面1)~6)就可以达到目的,但是如果需要将任务例行化(例如每天,每小时跑一次),则还需要进行PLSQL的开发。TDW SQL使用了python作为流程控制语言,所以要要完成这部分工作还需要了解一些python语言的基本语法和流程控制语法。

        TDW IDE同样提供了PLSQL的开发环境。

7) PLSQL开发和调试

        使用TDW IDE进行TDW PLSQL的开发与开发普通的python程序差别不大,需要先建立工程并进行一些简单的配置,然后就是新建python脚本,为了减少用户的工作量,TDW IDE对一些典型的应用场景进行了抽象,提供了一些脚本模板,由于大部分TDW PLSQL的流程大同小异,所以使用这些模板可以事半功倍。脚本开发完成后,如果需要在TDW IDE上直接运行或者调试脚本,则需要添加TDW连接配置文件。

8) 将PLSQL上传到洛子平台

        TDW IDE与调度系统—洛子进行了打通,用户可以在IDE中将脚本上传到洛子。

    SQL开发出来后,就可提交给TDW HIVE了。那么一条SQL究竟是怎么被翻译成MapReduce执行计划的呢?下面以一条SQL为例简要讲述HIVE的工作原理。

HIVE的架构和工作原理

blob.png

        HIVE的RPC Server在接收到客户端发送的SQL执行请求后,经过语法解析,语义分析生成一个逻辑执行计划,这个逻辑执行计划是一个由HIVE算子组成的DAG(无环有向图);然后逻辑执行计划被传送到HIVE 的优化器,优化器有采用一系列的优化规则(例如分区剪枝,列剪枝,JOIN算子合并,条件下推等)对原始的逻辑执行计划进行优化;最终优化后的逻辑执行计划中的算子被划分到一个个Map或者Reduce中,形成物理执行计划。物理执行计划是由一个个MapReduce job组成的DAG,HIVE本地有一个简单的MapReduce Job调度程序,这个调度程序按照这些MapReduce Job的依赖关系依次将这些Job提交给Hadoop来执行,提交之后,HIVE会不断轮询Job的执行信息,直至Job运行结束。在HIVE做权限认证和SQL解析时需要和HIVE的元数据集群交互来获取表的信息和存储格式等。

        下面以一条SQL为例详细说明HIVE的各大功能模块的工作原理。这是一条非常简单的SQL,包含JOIN和Group by。

SELECT

COUNT(fsubaction_id) fsubaction_id_num

FROM

(

SELECT

a.ftime ftime

,b.fuin fuin

,b.fsubaction_id fsubaction_id

,a.count_zr_num count_zr_num

FROM

hlw::f_qz_visit_d a

JOIN hlw::f_qz_write_m b

ON (a.fuin = b.fuin)

WHERE

a.ftime = 20130909

AND b.faction_id = 1111

)

GROUP BY

Fuin

语法解析

        语法解析实际上就是将原始的SQL解析成一颗语法树,方便后续模块处理。 HIVE使用Antlr作为作为语法解析的工具。

        Antlr—Another Tool for Language Recognition,其前身是PCCTS,它提供了一个通过语法描述来自动构造自定义语言的识别器(recognizer),编译器(parser)和解释器(translator)的框架。为了使用Antlr,首先需要制定语法规则,然后Antlr根据语法规则生成一个词法分析器(Lexical analyser)和语法分析器(Syntactical analyser)。

        原始的SQL首先被送入词法分析器,词法分析器将SQL变成一个离散的字符组(也就是一个一个的Token),包括关键字,标识符,运算符等;紧接着语法分析器将这些离散的字符组按照上下文环境组织起来并转换成为目标语言语法定义所允许的序列,最终这些序列组成了一棵完整的语法树(AST Tree)。示例SQL的JOIN子句部分翻译成的语法树如下图所示(完整的语法树非常复杂)。JOIN节点往下有三棵子树,分别代表左表信息,右表信息和连接条件。

blob.png

语义分析

        语义分析的本质就是遍历语法树,首先寻找到特定的子树(例如FROM子树,JOIN子树等),然后依照特定的顺序把这些子树转换成一个个算子。这些算子实际上组成了数据处理的流程,所以它们之间不是无序的,这就意味着算子的转换必须依照特定的顺序进行。例如首先生成的算子必然是TableScan,因为从表中读取数据是处理的第一步,一个典型的算子流程如下所示:

blob.png

 对于一些比较简单的子树,往往只需要生成一个算子,例如WHERE子树会生成一个FILTER算子。但是一些比较复杂的操作往往需要生成多个算子,例如GROUP BY操作,JOIN操作和分析函数等。

        以GROUP BY操作为例,它用到了MapReduce计算框架的分组和排序功能。所以他们需要先生成一个ReduceSinkOperator来设置Map阶段的输出key和value。

        GROUP BY操作需要以分组的列为Map的输出Key值,这样相同的key值就被shuffle到同一个Reduce中,方便后续计算。在某些情况下(Key值比较集中),首先进行局部聚合可以减少Map输出的数据量。

blob.png


blob.png

优化器

        优化器对HIVE来说是至关重要的,它是影响Job执行效率的主要因素之一。HIVE提供两种优化器。

        一是基于规则的优化器,具体的规则包括列裁剪,分区剪枝,条件下推等。这类优化器都是对原始的逻辑执行计划DAG进行遍历,调整算子的位置,修改算子所包含的信息进行,插入一些算子和对算子树进行等价转换等。例如列剪枝规则,它的基本过程是对逻辑执行计划DAG进行深度优先遍历,找到选择算子—SelectOperator,然后进行回溯,以选择算子为基准,修改每一个上游算子的输入输出列,去掉不需要的列,最后在最接近数据读取算子的地方插入一个选择算子,以尽可能的减少流经算子的数据量,提高计算效率。每种规则的具体遍历规则和处理方式都截然不同,但目的相似,都是为了减少算子处理的数据量。

        示例SQL经过基于规则的优化器处理后的逻辑执行计划如图所示。

12

 第二类优化器是基于代价的优化器,这种优化器需要依赖表的各种统计信息:表和分区的行数,行的大小,列值的离散程度等。它根据这些统计信息计算各种算法和执行计划的代价,找出其中最优的。这一类优化器的实现相当的复杂,收集这些统计信息也需要花费一些代价。目前,HIVE对这一类优化器的支持还需要进一步完善。

算子分发

        要使查询计划能够在Hadoop上运行,需要将逻辑查询计划(Operator DAG)转换为物理查询计划(MapReduce序列)。在这个过程中,要对Operator 树中的节点进行划分,把他们塞进不同的MapReduce中。这是在对Operator树进行一次先深遍历的过程中进行的,主要是划分出不同的MapReduce任务并保证他们之间的依赖关系正确。

        这个过程十分的复杂,划分的规则也非常多。其中用得最多的一条规则是以ReduceSinkOperator为划分的临界点(出现ReduceSinkOperator意味着需要使用MapReduce框架的shuffle,也就是Map和Reduce的分界线)。在划分的过程中,很多时候必须插入一些算子(例如FileSinkOperator和TableScanOperator)来保证划分的完整性, 这是由MapReduce计算模型的限制所决定的。

13

MapReduce Job提交

        得到最终的物理执行计划后,HIVE的执行模块将这些MapReduce Job以一定的次序提交给Hadoop执行:一个Job能够被执行的前提是它所依赖的所有的Job都已经执行完成;两个没有依赖关系的Job可以并发的执行。

        具体针对单个MapReduce Job,HIVE首先将该MapReduce对应的算子DAG序列化成一个执行计划文件,然后将这个文件和HIVE Jar包放入Hadoop的分布式缓存,这样每个具体执行计算的节点都可以轻松的获取到它们。在Map和Reduce的初始化阶段,这些执行计划文件被反序列化出来,然后Map和Reduce就可以按照算子DAG一步步完成计算。

下一步计划

        从上面的介绍也可以看得出来,HIVE还存在很多的不足:过多的数据落地次数不仅消耗IO资源,同时严重降低了SQL执行效率;MapReduce框架复杂的调度和启动过程也让SQL执行时间变长。针对HIVE的优化和改造依然任重而道远。

        在当前HIVE基本算法的基础上,实现更多有针对性的算法,提高计算效率

        完善基于代价的优化,以统计信息为依据,选择代价最小的执行计划

        引入MPP架构的执行框架,弥补当前HIVE在实时查询方面的不足

        引入DAG计算模型,减少数据落地次数


CIO之家 www.ciozj.com 公众号:imciow
关联的文档
也许您喜欢