Hive编程指南

978-7-115-33383-4
作者: 【美】Edward Capriolo Dean Wampler Jason Rutherglen
译者: 曹坤
编辑: 汪振
分类: Hadoop

图书目录:

详情

本书是一本Hive的编程指南。本书以案例为主,主要向读者介绍如何设置并优化Hive,以及如何与其他工具并用,如HBase等。还将介绍如何使用Java或脚本语言编写自定义代码来扩展Hive。全书将对Hive进行全面详实的介绍,主要适用于SQL专家,如数据库设计人员和业务分析师。我们也谈到了深入的技术细节,可以帮助Hadoop开发人员对Hive进行调优和定制。

图书摘要

版权信息

书名:Hive编程指南

ISBN:978-7-115-33383-4

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

• 著    [美] Edward Capriolo Dean Wampler Jason Rutherglen

  译    曹 坤

  责任编辑 汪 振

• 人民邮电出版社出版发行  北京市丰台区成寿寺路11号

  邮编 100164  电子邮件 315@ptpress.com.cn

  网址 http://www.ptpress.com.cn

• 读者服务热线:(010)81055410

  反盗版热线:(010)81055315


Copyright © 2013 by O’Reilly Media. Inc.

Simplified Chinese Edition, jointly published by O’Reilly Media, Inc. and Posts &; Telecom Press, 2013. Authorized translation of the English edition, 2013 O’Reilly Media, Inc., the owner of all rights to publish and sell same.

All rights reserved including the rights of reproduction in whole or in part in any form.

本书中文简体字版由O’Reilly Media, Inc.授权人民邮电出版社出版。未经出版者书面许可,对本书的任何部分不得以任何方式复制或抄袭。

版权所有,侵权必究。


本书是一本Apache Hive的编程指南,旨在介绍如何使用Hive的SQL方法——HiveQL来汇总、查询和分析存储在Hadoop分布式文件系统上的大数据集合。全书通过大量的实例,首先介绍如何在用户环境下安装和配置Hive,并对Hadoop和MapReduce进行详尽阐述,最终演示Hive如何在Hadoop生态系统进行工作。

本书适合对大数据感兴趣的爱好者以及正在使用Hadoop系统的数据库管理员阅读使用。


O’Reilly Media通过图书、杂志、在线服务、调查研究和会议等方式传播创新知识。自1978年开始,O’Reilly一直都是前沿发展的见证者和推动者。超级极客们正在开创着未来,而我们关注真正重要的技术趋势——通过放大那些“细微的信号”来刺激社会对新科技的应用。作为技术社区中活跃的参与者,O’Reilly的发展充满了对创新的倡导、创造和发扬光大。

O’Reilly为软件开发人员带来革命性的“动物书”;创建第一个商业网站(GNN);组织了影响深远的开放源代码峰会,以至于开源软件运动以此命名;创立了《Make》杂志,从而成为DIY革命的主要先锋;公司一如既往地通过多种形式缔结信息与人的纽带。O’Reilly的会议和峰会集聚了众多超级极客和高瞻远瞩的商业领袖,共同描绘出开创新产业的革命性思想。作为技术人士获取信息的选择,O’Reilly现在还将先锋专家的知识传递给普通的计算机用户。无论是通过书籍出版、在线服务或者面授课程,每一项O’Reilly的产品都反映了公司不可动摇的理念——信息是激发创新的力量。

“O’Reilly Radar博客有口皆碑。”

——Wired

“O’Reilly凭借一系列(真希望当初我也想到了)非凡想法建立了数百万美元的业务。”

——Business 2.0

“O’Reilly Conference是聚集关键思想领袖的绝对典范。”

——CRN

“一本O’Reilly的书就代表一个有用、有前途、需要学习的主题。”

——Irish Times

“Tim是位特立独行的商人,他不光放眼于最长远、最广阔的视野并且切实地按照Yogi Berra的建议去做了:‘如果你在路上遇到岔路口,走小路(岔路)。’回顾过去Tim似乎每一次都选择了小路,而且有几次都是一闪即逝的机会,尽管大路也不错。”

——Linux Journal


Edward Capriolo目前是Media6degrees公司的系统管理员,在这里他为互联网广告企业提供设计和维护分布式数据存储系统的服务。

Edward是Apache软件基金会的成员,同时也是Hadoop/Hive项目的贡献者。Edward具有软件开发经验,同时也具有Linux和网络管理员的经历,而且对于开源软件世界充满了热情。

Dean Wampler是ThinkBigAnalytics公司的首席顾问,其擅长“大数据”文件,以及像Hadoop这样的工具研究,还有机器学习相关的内容。除了擅长大数据,他还擅长Scala、JVM生态系统、JavaScript、Ruby、函数式以及面向对象编程,同时还擅长敏捷方法。Dean经常性地在工业和学术会议上就这些主题进行演讲。他还具有来自华盛顿大学的物理学博士学位。

Jason Rutherglen是Think Big Analytics公司的一名软件架构师,其擅长大数据、Hadoop、搜索和安全领域。


当我第一次参与到Hadoop里时,我看到了分布式文件系统和MapReduce计算框架可以以一种伟大的方式来解决计算密集型的问题。然而,使用MapReduce编程模型进行编程曾经对于我来说是件非常麻烦的事情。Hive提供了一个类SQL的方式可以让我快速而又简单地利用到MapReduce计算的优势。这种方法也使得概念验证应用程序原型设计变得容易,同时在内部可以很好地使用Hadoop作为解决方案。尽管我现在非常熟悉Hadoop内核,Hive仍然是我利用Hadoop进行工作的主要方法。

能够参与编写一本关于Hive的书,对我来说是一件非常荣耀的事情;同时能够作为一名Hive代码贡献者和Apache软件基金会的成员也是我最有价值的荣誉。

作为Think Big Analytics公司的一名“大数据”顾问,我经常和一群具有丰富经验的SQL“数据人”一起工作。对他们来说,使用Hive是必要且充分的,这样才能使用Hadoop作为可行的工具,并利用他们的SQL知识来使用数据分析,开创新的机遇。

Hive缺乏良好的文档。我向O’Reilly出版社的编辑Mike Loukides建议,社区确实需要一本Hive相关的书籍。于是,本书应运而生……

我是Think Big Analytics公司的一名软件架构师。我的职业生涯涉及一系列的技术,包括搜索、Hadoop、移动、密码学和自然语言处理。Hive是使用开源技术,基于海量数据构建数据仓库的最终方式。我在很多不同的项目中使用了Hive。


感谢参与到Hive中的每一个人。包括代码贡献者、参与者以及最终用户。

Mark Grove编写了Hive和亚马逊网络服务那一章的内容。他是一个Apache Hive 项目的贡献者并在Hive IRC上非常积极地帮助他人。M6D公司的David Ha和Rumit Pate贡献了案例研究章节的内容和等级函数的代码。在Hive中可以进行排名是一个重要的特性。

M6D公司的Stitelman,贡献了案例研究章节中关于数据科学如何使用Hive和R的内容,其中演示了如何通过Hive对大数据集进行一次处理并提供了产生的结果,然后在之后的处理过程中使用R处理Hive产生的结果数据。

David Funk贡献了3个用例,即:站内引用链接识别、会话化、计数独立用户访问量。David的技术说明展示了如何重写和优化Hive查询可以使数据分析效率得到大幅度提高。Ian Robertson审阅了整个书的初稿并提供非常有用的反馈信息。我们非常感谢他,在时间很紧的短时间内提供了这些反馈。

John Sichi 对本书进行了专业技术评审。John同时也帮助开发了Hive中的一些新特性,例如StorageHandlers和索引支持。他一直积极帮助支持Hive社区的成长。

Alan Gates,《Pig编程指南》的作者,贡献了关于HCatalog的那一章内容。Nanda Vijaydev贡献了关于Karmasphere公司如何将Hive进行增强并提供产品化的那一章内容。Eric Lubow提供了关于SimpleReach公司的案例研究。Chris A. Mattmann、Paul Zimdars、 Cameron Goodale、Andrew F. Hart、Jinwon Kim、Duane Waliser和Peter Lean共同贡献了美国宇航局喷气推进实验室(NASA JPL)的案例研究。


本书是一本Hive的编程指南。Hive是Hadoop生态系统中必不可少的一个工具,它提供了一种SQL(结构化查询语言)方言,可以查询存储在Hadoop分布式文件系统(HDFS)中的数据或其他和Hadoop集成的文件系统,如MapR-FS、Amazon的S3和像HBase(Hadoop数据库)和Cassandra这样的数据库中的数据。

大多数数据仓库应用程序都是使用关系数据库进行实现的,并使用SQL作为查询语言。Hive降低了将这些应用程序转移到Hadoop系统上的难度。凡是会使用SQL语言的开发人员都可以很轻松地学习并使用Hive。如果没有Hive,那么这些用户就必须学习新的语言和工具,然后才能应用到生产环境中。另外,相比其他工具,Hive更便于开发人员将基于SQL的应用程序转移到Hadoop中。如果没有Hive,那么开发者将面临一个艰巨的挑战,如何将他们的SQL应用程序移植到Hadoop上。

不过,Hive和其他基于SQL的环境还是有一些差异的。如今,可供Hive用户和Hadoop开发者使用的文档并不多,所以我们决定撰写这本书来填补这个缺口。我们将对Hive进行全面详实的介绍,主要适用于SQL专家,如数据库设计人员和业务分析师。我们也谈到了深入的技术细节,可以帮助Hadoop开发人员对Hive进行调优和定制。

用户可以在本书的目录页面了解到更多信息:http://oreil.ly/Programming_Hive

本书中使用到了如下几种印刷字体。

斜体字

表明是新的术语、URL、电子邮件地址、文件名或者文件扩展名。

等宽字体

用于程序列表,同时段落中使用到的了程序片段,例如变量或者函数名称、数据库、数据类型、环境变量、语句和关键字。

等宽粗体

表示是命令或者其他需要用户进行输入的文本。

等宽斜体

表示这个文本需要用户提供对应的值或者需要通过上下文才能获取到的值。

 提示

这个图标表明是一个小技巧、建议或者一般性的注释。

 

 警告

这个图标表明是个警告或者警示。

本书的目的是帮助用户完成他们的任务。通常情况下,用户可以在他们的程序和文档中使用本书中的代码。如此不需要联系我们以获取许可,除非明显地复制了代码的大部分内容。例如,写程序用到了本书中几个代码片段是不需要获得许可的,但是如果销售或者传播包含了O’Reilly系列书籍中的例子的CD光盘,那么就一定要获得我们的许可才行。在回答问题时引用到本书或以本书中的例子为引证时不需要获得许可,将一定数量的样例代码复制到自己的产品文档中则一定需要获得我们的许可才可以。

虽然并非是必需的,但如果可以注明出处,我们将十分感激。出处一般包括标题,作者,出版商和ISBN。例如:“Programming Hive by Edward Capriolo, Dean Wampler, and Jason Rutherglen (O’Reilly). Copyright 2012 Edward Capriolo, Aspect Research Associates, and Jason Rutherglen, 978-1-449-31933-5.”

如果用户感觉自己没有合理地或者在如上所述的许可范围内使用本书中代码样例的话,请尽管通过 permissions@oreilly.com联系我们。

Safari在线图书是一个按需服务的数字图书馆。使用它,用户可以轻松检索超过7 500本技术和创意参考书以及视频教程,快速获得想知道的答案。

通过订阅,用户可以从我们的在线图书馆中阅读每一篇文章或观看每一部视频。通过用户的手机和其他移动设备看书。在书还没有印刷前就可以事先看到书目,还可以看到正在进行中的草稿,并可以将意见反馈给作者。复制粘贴代码样例,组织用户的收藏夹,下载一些章节,对关键章节标记标签,创建笔记,打印书籍内容,并通过其他众多的省时功能而受益。

O’Reilly公司已经将本书上传到 Safari图书在线服务。想获得对这本书的完整数据版访问权限以及其他的来源于O’Reilly和其他出版商的对相同话题的讨论,请通过网址http://my.safaribooksonline.com免费注册账户。

请将对于本书的评论和问题通过如下地址发送给出版商:

O’Reilly Media, Inc.

1005 Gravenstein Highway North

Sebastopol, CA 95472

800-998-9938 (in the United States or Canada)

707-829-0515 (international or local)

707-829-0104 (fax)

在本书的官方页面中,我们列举了勘误表、例子和其他附加信息,用户可以通过以下链接访问:

http://oreil.ly/Programming_Hive

可以通过如下E-mail,将用户对本书的评论或技术方面的问题发送给我们:

bookquestions@oreilly.com

想获得更多关于我们的系列书籍、会议、资源中心和O’Reilly网络公司,请通过如下网站查看:

http://www.oreilly.com

我们的Fackbook地址是:http://facebook.com/oreilly

我们的Twitter地址是:http://twitter.com/oreillymedia

我们的YouTube地址是:http://www.youtube.com/oreillymedia


从早期的互联网主流大爆发开始,主要的搜索引擎公司和电子商务公司就一直在和不断增长的数据进行较量。最近,社交网站也遇到了同样的问题。如今,许多组织已经意识到他们所收集的数据是让他们了解他们的用户,提高业务在市场上的表现以及提高基础架构效率的一个宝贵的资源。

Hadoop生态系统就是为处理如此大数据集而产生的一个合乎成本效益的解决方案。Hadoop实现了一个特别的计算模型,也就是MapReduce,其可以将计算任务分割成多个处理单元然后分散到一群家用的或服务器级别的硬件机器上,从而降低成本并提供水平可伸缩性。这个计算模型的下面是一个被称为Hadoop分布式文件系统(HDFS)的分布式文件系统。这个文件系统是“可插拔的”,而且现在已经出现了几个商用的和开源的替代方案。

不过,仍然存在一个挑战,那就是用户如何从一个现有的数据基础架构转移到Hadoop上,而这个基础架构是基于传统关系型数据库和结构化查询语句(SQL)的。对于大量的SQL用户(包括专业数据库设计师和管理员,也包括那些使用SQL从数据仓库中抽取信息的临时用户)来说,这个问题又将如何解决呢?

这就是Hive出现的原因。Hive提供了一个被称为Hive查询语言(简称HiveQL或HQL)的SQL方言,来查询存储在Hadoop集群中的数据。

SQL知识分布广泛的一个原因是:它是一个可以有效地、合理地且直观地组织和使用数据的模型。即使对于经验丰富的Java开发工程师来说,将这些常见的数据运算对应到底层的MapReduce Java API也是令人畏缩的。Hive可以帮助用户来做这些苦活,这样用户就可以集中精力关注于查询本身了。Hive可以将大多数的查询转换为MapReduce任务(job),进而在介绍一个令人熟悉的SQL抽象的同时,拓宽Hadoop的可扩展性。如果用户对此存在疑惑,请参考稍后部分的第1.3节“Java和Hive:词频统计算法”中的相关介绍。

Hive最适合于数据仓库应用程序,使用该应用程序进行相关的静态数据分析,不需要快速响应给出结果,而且数据本身不会频繁变化。

Hive不是一个完整的数据库。Hadoop以及HDFS的设计本身约束和局限性地限制了Hive所能胜任的工作。其中最大的限制就是Hive不支持记录级别的更新、插入或者删除操作。但是用户可以通过查询生成新表或者将查询结果导入到文件中。同时,因为Hadoop是一个面向批处理的系统,而MapReduce任务(job)的启动过程需要消耗较长的时间,所以Hive查询延时比较严重。传统数据库中在秒级别可以完成的查询,在Hive中,即使数据集相对较小,往往也需要执行更长的时间[1]。最后需要说明的是,Hive不支持事务。

因此,Hive不支持OLTP(联机事务处理)所需的关键功能,而更接近成为一个OLAP(联机分析技术)工具。但是我们将会看到,由于Hadoop本身的时间开销很大,并且Hadoop所被设计用来处理的数据规模非常大,因此提交查询和返回结果是可能具有非常大的延时的,所以Hive并没有满足OLAP中的“联机”部分,至少目前并没有满足。

如果用户需要对大规模数据使用OLTP功能的话,那么应该选择使用一个NoSQL数据库,例如,和Hadoop结合使用的HBase[2]及Cassandra[3]。如果用户使用的是Amazon弹性MapReduce计算系统(EMR)或者弹性计算云服务(EC2)的话,也可以使用DynamoDB[4]。用户甚至可以和这些数据库(还包括其他一些数据库)结合来使用Hive,这个我们会在第17章进行介绍。

因此,Hive是最适合数据仓库应用程序的,其可以维护海量数据,而且可以对数据进行挖掘,然后形成意见和报告等。

因为大多数的数据仓库应用程序是使用基于SQL的关系型数据库实现的,所以Hive降低了将这些应用程序移植到Hadoop上的障碍。用户如果懂得SQL,那么学习使用Hive将会很容易。如果没有Hive,那么这些用户就需要去重新学习新的语言和新的工具后才能进行生产。

同样地,相对于其他Hadoop语言和工具来说,Hive也使得开发者将基于SQL的应用程序移植到Hadoop变得更加容易。

不过,和大多数SQL方言一样,HiveQL并不符合ANSI SQL标准,其和Oracle,MySQL,SQL Server支持的常规SQL方言在很多方面存在差异(不过,HiveQL和MySQL提供的SQL方言最接近)。

因此,本书共有两个目的。其一,本书提供了一个针对所有用户的介绍。这个介绍会比较综合,并且会使用例子来进行讲解。适用的用户包括开发者、数据库管理员和架构师,以及其他(如商业分析师等)非技术类用户。

其二,本书针对开发者和Hadoop管理员等需要深入了解Hive技术细节的用户提供了更详尽的讲述,以帮助这些用户学习如何优化Hive查询性能,如何通过用户自定义函数和自定义数据格式等,来个性化使用Hive。

因为Hive缺少好的文档,所以我们经历了不少的挫折才完成了这本书。特别是对于那些非开发者以及不习惯通过查看项目BUG记录和功能数据库、源代码等途径来获取其所需信息的用户,Hive并没有提供好的文档。Hive Wiki[5]提供的信息价值很大,但是其中的解释有时太少了,而且常常没有进行及时的更新。我们希望本书可以弥补这些不足,可以提供一个对于Hive的所有基本功能以及如何高效使用这些功能的综合性的指南[6]

如果用户已经熟悉Hadoop和MapReduce计算模型的话,那么可以跳过本节。虽然用户无需精通MapReduce就可以使用Hive,但是理解MapReduce的基本原理将帮有助于用户了解Hive在底层是如何运作的,以及了解如何才能更高效地使用Hive。

我们在这里提供了一个关于Hadoop和MapReduce的简要描述。更多细节,请参考Tom White (O’Reilly)所著的《Hadoop权威指南》一书。

MapReduce是一种计算模型,该模型可将大型数据处理任务分解成很多单个的、可以在服务器集群中并行执行的任务。这些任务的计算结果可以合并在一起来计算最终的结果。

MapReduce编程模型是由谷歌(Google)开发的。Google通过一篇很有影响力的论文对这个计算模型进行了描述,本书附录部分可查看到该论文,名为《MapReduce:大数据之上的简化数据处理》。一年后,另一篇名为《Google文件系统》的论文介绍了Google文件系统。这两篇论文启发了道·卡丁(Doug Cutting)开发了Hadoop。

MapReduce这个术语来自于两个基本的数据转换操作:map过程和reduce过程。一个map操作会将集合中的元素从一种形式转换成另一种形式。在这种情况下,输入的键-值对会被转换成零到多个键-值对输出。其中,输入和输出的键必须完全不同,而输入和输出的值则可能完全不同。

在MapReduce计算框架中,某个键的所有键-值对都会被分发到同一个reduce操作中。确切地说,这个键和这个键所对应的所有值都会被传递给同一个Reducer。reduce过程的目的是将值的集合转换成一个值(例如对一组数值求和或求平均值),或者转换成另一个集合。这个Reducer最终会产生一个键-值对。再次说明一下,输入和输出的键和值可能是不同的。需要说明的是,如果job不需要reduce过程的话,那么也是可以无reduce过程的。

Hadoop提供了一套基础设施来处理大多数困难的工作以保证任务能够执行成功。例如,Hadoop决定如果将提交的job分解成多个独立的map和reduce任务(task)来执行,它就会对这些task进行调度并为其分配合适的资源,决定将某个task分配到集群中哪个位置(如果可能,通常是这个task所要处理的数据所在的位置,这样可以最小化网络开销)。它会监控每一个task以确保其成功完成,并重启一些失败的task。

Hadoop分布式文件系统(也就是HDFS),或者一个同类的分布式文件系统,管理着集群中的数据。每个数据块(block)都会被冗余多份(通常默认会冗余3份),这样可以保证不会因单个硬盘或服务器的损坏导致数据丢失。同时,因为其目标是优化处理非常大的数据集,所以HDFS以及类似的文件系统所使用的数据块都非常大,通常是64MB或是这个值的若干倍。这么大的数据块可以在硬盘上连续进行存储,这样可以保证以最少的磁盘寻址次数来进行写入和读取,从而最大化提高读写性能。

为了更清晰地介绍MapReduce,让我们来看一个简单的例子。Word Count算法已经被称为是MapReduce计算框架中的“Hello World”程序[7]了。Word Count会返回在语料库(单个或多个文件)中出现的所有单词以及单词出现的次数。输出内容会显示每个单词和它的频数,每行显示一条。按照通常的习惯,单词(输出的键)和频数(输出的值)通常使用制表符进行分割。

图1-1 显示了在MapReduce计算框架中Word Count程序是如何运作的。

图1-1 使用MapReduce执行WordCount算法

这里有很多内容要讲,所以我们会从左到右来讲解这个图。

图1-1中左边的每个Input(输入)框内都表示一个单独的文件。例子中有4个文件,其中第3个文件是个空文件,为了便于简单描述,其他3个文件都仅仅包含有少量几个单词。

默认情况下,每个文档都会触发一个Mapper进程进行处理。而在实际场景下,大文件可能会被划分成多个部分,而每个部分都会被发送给一个Mapper进行处理。同时,也有将多个小文件合并成一个部分供某个Mapper进行处理的方法。不过,我们当前不必深究这些细节性问题。

MapReduce计算框架中的输入和输出的基本数据结构是键-值对。当Mapper进程启动后,其将会被频繁调用来处理文件中的每行文本。每次调用中,传递给Mapper的键是文档中这行的起始位置的字符偏移量。对应的值是这行对应的文本。

在WordCount程序中,没有使用字符偏移量(也就是没有使用键)。值(也就是这行文本)可以使用很多种方式进行分割(例如,按照空格分隔是最简单的方式,但是这样会遗留下不需要的标点符号),最终这行文本会被分解成多个单词。我们同时假定Mapper会将每个单词转换成小写,因此对于“FUN”和“fun”会被认为是同一个单词。

最后,对于这行文本中的每个单词,Mapper都会输出一个键-值对,以单词作为键并以数字1作为值(这里1表示“出现1次”)。需要注意的是键和值的输出数据类型和输入数据类型是不同的。

Hadoop神奇的地方一部分在于后面要进行的Sort(排序)和Shuffle(重新分发)过程。Hadoop会按照键来对键-值对进行排序,然后“重新洗牌”,将所有具有相同键的键-值对分发到同一个Reducer中。这里有多种方式可以用于决定哪个Reducer获取哪个范围内的键对应的数据。这里我们先不必考虑这些问题。但是出于说明性目的,我们假设图中使用了一个特殊的按字母数字划分的过程(在实际执行中,会有所不同)。

对于Mapper而言如果只是简单地对每个单词输出计数1这样的处理的话,那么会在Sort和Shuffle过程中产生一定的网络和磁盘I/O浪费(不过,这样并不会减少Mapper的内存使用)。有一个优化就是跟踪每个单词的频数,然后在Mapper结束后只输出每个单词在这个Mapper中的总频数。对于这个优化有好几种实现方式,但是,最简单的方式应该是逻辑是正确的,而且对于这个讨论,理由是充足的。

每个Reducer的输入同样是键-值对,但是这次,每个键将是Mapper所发现的单词中的某一个单词,而这个键对应的值将是所有Mapper对于这个单词计算出的频数的一个集合。需要注意的是键的数据类型和值的集合中元素的数据类型和Mapper的输出是一致的。也就是说,键的类型是一个字符串,而集合中的元素的数据类型是整型。

为了完成这个算法,所有的Reducer需要做的事情就是将值集合中的频数进行求和然后写入每个单词和这个单词最终的频数组成的键-值对。

Word Count不是一个虚构的例子。这个程序所产生的数据可用于拼写检查程序、计算机语言检测和翻译系统,以及其他应用程序。

WordCount算法,和基于Hadoop实现的大多数算法一样,有那么点复杂。当用户真正使用Hadoop的API来实现这种算法时,甚至有更多的底层细节需要用户自己来控制。这是一个只适用于有经验的Java开发人员的工作,因此也就将Hadoop潜在地放在了一个非程序员用户无法触及的位置,即使这些用户了解他们想使用的算法。

事实上,许多这些底层细节实际上进行的是从一个任务(job)到下一个任务(job)的重复性工作,例如,将Mapper和Reducer一同写入某些数据操作构造这样的底层的繁重的工作,通过过滤得到所需数据的操作,以及执行类似SQL中数据集键的连接 (JOIN)操作等。不过幸运的是,存在一种方式,可以通过使用“高级”工具自动处理这些情况来重用这些通用的处理过程。

这也就是引入Hive的原因。Hive不仅提供了一个熟悉SQL的用户所能熟悉的编程模型,还消除了大量的通用代码,甚至是那些有时是不得不使用Java编写的令人棘手的代码。

这就是为什么Hive对于Hadoop是如此重要的原因,无论用户是DBA还是Java开发工程师。Hive可以让你花费相当少的精力就可以完成大量的工作。

图1-2显示了Hive的主要“模块”以及Hive是如何与Hadoop交互工作的。

图1-2 Hive组成模块

有好几种方式可以与Hive进行交互。本书中,我们将主要关注于CLI,也就是命令行界面。对于那些更喜欢图形用户界面的用户,可以使用现在逐步出现的商业和开源的解决方案,例如Karmasphere发布的一个商业产品(http://karmasphere.com),Cloudera提供的开源的Hue项目(https://github.com/cloudera/hue),以及Qubole提供的“Hive即服务”方式(http://qubole.com),等。

Hive发行版中附带的模块有CLI,一个称为Hive网页界面(HWI)的简单网页界面,以及可通过JDBC、ODBC和一个Thrift服务器(参考第16章)进行编程访问的几个模块。

所有的命令和查询都会进入到Driver(驱动模块),通过该模块对输入进行解析编译,对需求的计算进行优化,然后按照指定的步骤执行(通常是启动多个MapReduce任务(job)来执行)。当需要启动MapReduce任务(job)时,Hive本身是不会生成Java MapReduce算法程序的。相反,Hive通过一个表示“job执行计划”的XML文件驱动执行内置的、原生的Mapper和Reducer模块。换句话说,这些通用的模块函数类似于微型的语言翻译程序,而这个驱动计算的“语言”是以XML形式编码的。

Hive通过和JobTracker通信来初始化MapReduce任务(job),而不必部署在JobTracker所在的管理节点上执行。在大型集群中,通常会有网关机专门用于部署像Hive这样的工具。在这些网关机上可远程和管理节点上的JobTracker通信来执行任务(job)。通常,要处理的数据文件是存储在HDFS中的,而HDFS是由NameNode进行管理的。

Metastore(元数据存储)是一个独立的关系型数据库(通常是一个MySQL实例),Hive会在其中保存表模式和其他系统元数据。在我们将详细进行讨论。

尽管本书是关于Hive的,不过还是有必要提及其他的一些高级工具,这样用户可以根据需求进行选择。Hive最适合于数据仓库程序,对于数据仓库程序不需要实时响应查询,不需要记录级别的插入、更新和删除。当然,Hive也非常适合于有一定SQL知识的用户。不过,用户的某些工作可能采用其他的工具会更容易进行处理。

Hive的替代工具中最有名的就是Pig了(请参考http://pig.apache.org)。Pig是由Yahoo!开发完成的,而同时期Fackbook正在开发Hive。Pig现在同样也是一个和Hadoop紧密联系的顶级Apache项目。

假设用户的输入数据具有一个或者多个源,而用户需要进行一组复杂的转换来生成一个或者多个输出数据集。如果使用Hive,用户可能会使用嵌套查询(正如我们将看到的)来解决这个问题,但是在某些时刻会需要重新保存临时表(这个需要用户自己进行管理)来控制复杂度。

Pig被描述成一种数据流语言,而不是一种查询语言。在Pig中,用户需要写一系列的声明语句来定义某些关系和其他一些关系之间的联系,这里每个新的关系都会执行新的数据转换过程。Pig会查找这些声明,然后创建一系列有次序的MapReduce任务(job),来对这些数据进行转换,直到产生符合用户预期的计算方式所得到的最终结果。

这种步进式的数据“流”可以比一组复杂的查询更加直观。也因此,Pig常用于ETL(数据抽取,数据转换和数据装载)过程的一部分,也就是将外部数据装载到Hadoop集群中,然后转换成所期望的数据格式。

Pig的一个缺点就是其所使用的定制语言不是基于SQL的。这是可以理解的,因为Pig本身就不是被设计为一种查询语言的,但是这也意味着不适合将SQL应用程序移植到Pig中,而经验丰富的SQL用户可能需要投入更高的学习成本来学习Pig。

然而, Hadoop团队通常会将Hive和Pig结合使用,对于特定的工作选择合适的工具。

Alan Gates(O’Reilly)所编著的《Pig编程指南》一书对于Pig进行了全面的介绍。

如果用户需要Hive无法提供的数据库特性(如行级别的更新,快速的查询响应时间,以及支持事务)的话,那么该怎么办呢?

HBase是一个分布式的、可伸缩的数据存储,其支持行级别的数据更新、快速查询和行级事务(但不支持多行事务)。

HBase的设计灵感来自于谷歌(Google)的BigTable,不过HBase并没有实现BigTable的所有特性。HBase支持的一个重要特性就是列存储,其中的列可以组织成列族。列族在分布式集群中物理上是存储在一起的。这就使得当查询场景涉及的列只是所有列的一个子集时,读写速度会快得多。因为不需要读取所有的行然后丢弃大部分的列,而是只需读取需要的列。

可以像键-值存储一样来使用HBase,其每一行都使用了一个唯一键来提供非常快的速度读写这一行的列或者列族。HBase还会对每个列保留多个版本的值(按照时间戳进行标记),版本数量是可以配置的,因此,如果需要,可以“时光倒流”回退到之前的某个版本的值。

最后,HBase和Hadoop之间是什么关系?HBase使用HDFS(或其他某种分布式文件系统)来持久化存储数据。为了可以提供行级别的数据更新和快速查询,HBase也使用了内存缓存技术对数据和本地文件进行追加数据更新操作日志。持久化文件将定期地使用附加日志更新进行更新等操作。

HBase没有提供类似于SQL的查询语言,但是Hive现在已经可以和HBase结合使用了。在第17.3节“HBase”中我们将讨论这个结合。

关于HBase的更多信息,请参考HBase的官方网站,以及参阅LarsGeorge所著的《HBase权威指南》一书。

Apache Hadoop生态系统之外还有几个“高级”语言,它们也在Hadoop之上提供了不错的抽象来减少对于特定任务(job)的底层编码工作。为了叙述的完整性,下面我们列举其中的一些来进行介绍。所有这些都是JVM(Java虚拟机)库,可用于像Java、Clojure、Scala、JRuby、Groovy和Jython,而不是像Hive和Pig一样使用自己的语言工具。

使用这些编程语言既有好处也有弊端。它使这些工具很难吸引熟悉SQL的非程序员用户。不过,对于开发工程师来说,这些工具提供了图灵完全的编程语言的完全控制。Hive和Pig都是图灵完全性的(译者注:图灵完全性通常是指具有无限存储能力的通用物理机器或编程语言)。当我们需要Hive本身没有提供的额外功能时,我们需要学习如何用Java编码来扩展Hive功能(见表1-1)。

表1-1 其他可选的Hadoop之上的高级语言库

名称

URL

描述

Casading

http://cascading.org

提供数据处理抽象的Java API。目前有很多支持Casading的特定领域语言(DSL),采用的是其他的编程语言,例如Scala、Groovy、JRuby和Jython

Casalog

https://github.com/nathanmarz/
cascaLog

Casading的一个Clojure DSL,其提供了源于Datalog处理和查询抽象过程灵感而产生的附属功能

Crunch

https://github.com/cloudera/crunch

提供了可定义数据流管道的Java和Scala API

因为Hadoop是面向批处理系统的,所以存在更适合事件流处理的使用不同的分布式计算模式的工具。对事件流进行处理时,需要近乎“实时”响应。这里我们列举了其中一些项目(见表1-2)。

表1-2 没有使用MapReduce的分布式处理工具

名称

URL

描述

Spark

http://www.spark-project.org/

一个基于Scala API的分布式数据集的分布式计算框架。其可以使用HDFS文件,而且其对于MapReduce中多种计算可以提供显著的性能改进。同时还有一个将Hive指向Spark的项目,称作Shark(http://shark.cs.berkeley.edu/

Storm

https://github.com/
nathanmarz/storm

一个实时事件流处理系统

Kafka

http://incubator.apache.org
/kafka/index.html

一个分布式的发布-订阅消息传递系统

最后,当无需一个完整的集群时(例如,处理的数据集很小,或者对于执行某个计算的时间要求并不苛刻),还有很多可选的工具可以轻松地处理原型算法或者对数据子集进行探索。表1-3列举了一些相对比较热门的工具。

表1-3 其他数据处理语言和工具

名称

URL

描述

R

http://r-project.org/

一个用于统计分析和数据图形化展示的开源语言,通常在数据与统计学家、经济学家等人群中很受欢迎。R不是一个分布式系统,所有其可以处理的数据大小是有限的。社区正努力将R和Hadoop结合起来

Matlab

http://www.mathworks.com/
products/matlab/index.html

一个受工程师和科学家欢迎的商业数据分析和数值方法计算系统

Octave

http://www.gnu.org/
software/octave/

Matlab对应的一个开源版

Mathematica

http://www.wolfram.com/
mathematica/

一个商业数据分析、人工智能和数值方法运算系统,这是个可以受科学家和工程师欢迎的工具

SciPy,NumPy

http://scipy.org

数据科学家广泛使用的、使用Python进行科学编程的软件

如果用户不是Java工程师,那么可以直接跳到下一节。

如果用户是名Java工程师,那么可能需要阅读本节,因为用户需要为其所在组织的Hive用户提供技术支持。你可能会质疑如何使用Hive解决自己的工作。如果是这样的话,那么可以先看看下面这个实现了之前我们所讨论的Word Count算法的例子,我们先学会使用Java MapReduce API,然后再学习如何使用Hive。

通常都会使用Word Count作为用户学习使用Java编写MapReduce程序的例子,因为这样用户可以关注于API。因此,Word Count已经成为Hadoop世界中的“Hello World”程序了。

Apache Hadoop 分支版本中包含有下面的这个Java实现[8]。如果读者并不了解Java(但是你仍在读本节内容的话),也不必担心,我们提供这个代码只是为了方便用户进行大小对比。

package org.myorg;

import java.io.IOException;
import java.util.*;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.conf.*;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.*;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;

public class WordCount {

public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> {
  private final static IntWritable one = new IntWritable(1);
  private Text word = new Text();

  public void map(LongWritable key, Text value, Context context)
   throws IOException, InterruptedException {
    String line = value.toString();
    StringTokenizer tokenizer = new StringTokenizer(line);
    while (tokenizer.hasMoreTokens()) {
      word.set(tokenizer.nextToken());
      context.write(word, one);
     }
   }
}

  public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable> {
    public void reduce(Text key, Iterable<IntWritable> values, Context context)
     throws IOException, InterruptedException {
      int sum = 0;
      for (IntWritable val : values) {
        sum += val.get();
       }
       context.write(key, new IntWritable(sum));
    }
}

public static void main(String[] args) throws Exception {
  Configuration conf = new Configuration();

  Job job = new Job(conf, "wordcount");

  job.setOutputKeyClass(Text.class);
  job.setOutputValueClass(IntWritable.class);

  job.setMapperClass(Map.class);
  job.setReducerClass(Reduce.class);

  job.setInputFormatClass(TextInputFormat.class);
  job.setOutputFormatClass(TextOutputFormat.class);

  FileInputFormat.addInputPath(job, new Path(args[0]));
  FileOutputFormat.setOutputPath(job, new Path(args[1]));

  job.waitForCompletion(true);
 }
}

上面是一个有63行的Java代码。我们不会详细解释其中的API[9]。如下是使用HiveQL进行的相同的运算,这时只有8行代码,而且不需要进行编译然后生成一个“JAR”(Java压缩包)文件。

CREATE TABLE docs (line STRING);

LOAD DATA INPATH 'docs' OVERWRITE INTO TABLE docs;
CREATE TABLE word*counts AS
SELECT word, count(1) AS count FROM
 (SELECT explode(split(line, '\s')) AS word FROM docs) w
GROUP BY word
ORDER BY word;

我们稍后会解释所有这些HiveQL语法。

在上面两个例子中,都是使用尽可能简单的方法将文件中的内容分割成单词,也就是按照空格进行划分的。这个方法不能很好地处理标点,同时也不能识别同一个单词的单数和复数形式,等等。不过,这里这么使用已经可以达到我们的目的了。[10]

借助Java API可以定制和调整一个算法实现的每个细节。不过,大多数情况下,用户都不需要这个级别的控制,而且当用户需要控制所有那些细节时也会相当地放慢用户的开发进度。

如果你不是一名程序员,那么也就用不着写Java MapReduce代码了。不过,如果你已经熟悉SQL了,那么学习Hive将会相当地容易,而且很多程序也都很容易快速实现。

我们描述了Hive在Hadoop生态系统中所扮演的重要角色。现在我们开始!

[1]不过,因为Hive是被设计用来处理的大数据集的,这个启动所消耗的时间和实际数据处理时间相比是微乎其微的。

[2]请访问Apache HBase的官方网站,http://hbase.apache.org,以及Lars George(O’Reilly)所著的《HBase权威指南》一书。

[3]请参考Cassandra的官方网站,http://cassandra.apache.org/,以及参考Edward Capriolo (Packt)所著的《High Performance Cassandra Cookbook》一书。

[4]请参考DynamoDB的官方网站,http://aws.amazon.com/dynamodb/

[5]参考链接 https://cwiki.apache.org/Hive/

[6]不过,非常有必要将这个wiki链接加入到网址收藏夹中,因为wiki中包含了一些我们没有覆盖的、比较模糊的信息。

[7]对于不是开发者的用户,这里需要补充说明的是“Hello World”程序通常是学习一门新的语言或者工具集的第一个程序。

[8]Apache Hadoop word count: http://wiki.apache.org/hadoop/WordCount.

[9]详细信息请参考Tom White所著的《Hadoop权威指南》一书。

[10]还有一个微小的差异。Hive查询硬编码指定一个指向数据的路径,而Java代码把这个路径作为一个输入参数处理。在第2章,我们将学习如何在Hive脚本中使用*变量*来避免这种硬编码。


相关图书

Hadoop虚拟化
Hadoop虚拟化
大数据开发者权威教程:NoSQL、Hadoop组件及大数据实施
大数据开发者权威教程:NoSQL、Hadoop组件及大数据实施
Hadoop海量数据处理:技术详解与项目实战(第2版)
Hadoop海量数据处理:技术详解与项目实战(第2版)
Hadoop海量数据处理:技术详解与项目实战
Hadoop海量数据处理:技术详解与项目实战
Hadoop MapReduce实战手册
Hadoop MapReduce实战手册
Hadoop MapReduce性能优化
Hadoop MapReduce性能优化

相关文章

相关课程