Pig编程指南(txt+pdf+epub+mobi电子书下载)

作者:[美]Alan Gates 著

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Pig编程指南

Pig编程指南试读:

前言

数据成瘾

数据是可以令人上瘾的。在过去数十年里我们收集和存储数据的能力已经大幅度提高。然而我们对于获取更多数据的欲望依旧没有得到满足。科学家们希望能够存储更多的数据以建立可以用来描述这个世界的更好的数学模型。市场营销者想通过数据了解他们的客户的意愿和消费习惯。金融分析师想通过数据更好地了解他们的市场运作情况。还有每个人都想保留各自的数码照片、电影、电子邮件等。

计算机和互联网的多次革命大大提高了我们收集和存储数据的能力。在这些革命之前,美国国会图书馆是世界上数据收集量最大的机构之一。曾经估算过它的印刷类书籍刊物包含的信息量大约能达到10TB。如今大型互联网公司一天的数据量就可以达到这么多。同时并非只有网络程序正以惊人的速率产生着数据。例如,计划在智利建造的大口径全景巡天望远镜(LSST)预计将会每天产生20TB的数据。

导致数据这种海量增长的部分原因是我们具有收集更多数据的能力。每当用户在网站上点击网页,Web服务器就会记录下该用户目前停留在哪个页面以及点击了哪些链接这样的信息。高速公路上每当一辆车驶过传感器的时候,车的行驶速度就会被记录下来。但是数据能够如此海量增长的更多原因是我们具备了海量数据存储的能力。十年前,望远镜每天晚上都会对星空拍摄很多的照片,但是这些照片并非全部都能以同一级别的分辨率存储,一些数据信息会被丢弃,因为根本没有足够的空间来存储它们。但是LSST正式运作后,这将不再是个问题。收集和存储海量数据的能力只是满足了我们的数据癖好。

在过去几十年里计算机系统中通常使用的数据存储和数据处理的工具之一就是关系型数据库管理系统(RDBMS)。但是随着数据集的不断增大,只有更高级的(也因此更加昂贵的)关系型数据库管理系统才能够达到目前很多用户所期望的标准。同时,许多涉及处理数据的工程师和科学家们意识到他们并不需要RDBMS提供的每一项功能。这些系统确实很强大而且功能很多,但是许多需要处理TB或者PB级别数据的用户只需要使用其中的一小部分功能。

RDBMS的高成本和非必需的功能导致了一些非主流的数据处理系统的出现,Apache Hadoop就是这些非主流的系统之一。Hadoop是由Doug Cutting 发起的一个开源项目。它是基于Google发表的多篇论文而实现的,这些论文描述了Google的工程师们是如何对他们收集的海量数据进行存储和处理的。在过去的几年,雅虎和其他一些互联网公司共同推动了Hadoop的发展。如果想了解Hadoop的发展历史,请阅读Tom White(O’Reilly出版社出版)所著的 《Hadoop: 编程指南》一书。Hadoop需要被部署到集群机器中,它可以提供一种利用集群力量进行存储和处理的方法。

像Hadoop这样的新型数据处理系统的发展促使了已经存在的工具和语言对Hadoop的移植,以及新工具(如Apache Pig)的构造。像Pig这样的工具为数据使用者提供了一种较高层次的抽象,为使用者提供了一种可以使用到Hadoop强大的处理能力和灵活性的方式,而并不需要他们用低层Java代码来编写大量的数据处理程序。谁应该读这本书

这本书是为Pig开发者准备的,无论是新手还是具有一定经验的开发者。之前从没有接触过Pig的人会在书中发现一些有用的入门性介绍,包括如何运行Pig以及怎么开始书写Pig Latin脚本。对于经验丰富的Pig使用者,这本书介绍了Pig几乎所有的功能:它可以从使用哪些不同的模式运行,Pig Latin语言的详细介绍,以及如何在Pig中开发用户自定义函数(UDF)。甚至对于那些使用Pig很久的用户也可能会在这本书里发现之前他们从未使用过的功能。

作为一个相对年轻的项目,在过去的4年里Pig有了相当大的变化和成长。在这段时间里,我们从发布0.1版本一直到发布0.9版本。本书是以Pig 0.7版本为基础展开的。对于0.8或0.9版本中特有的功能,书中在介绍的时候会进行说明。0.6版本到0.7版本的最大不同是对加载函数接口和存储函数接口这两个接口进行了重写,因此第11章的内容对于使用0.6或更低版本的用户是不适用的。当然,本书其他章节对于较早版本同样适用。

对于读者和Pig使用者来说,如果对Hadoop有所了解,那么阅读本书是有帮助的。附录B对Hadoop进行了简要的介绍而且说明了它是如何工作的。第1.1.1小节“Pig是基于Hadoop的”提供了一个简单的Hadoop任务的例子。对于那些不熟悉Hadoop的用户,这几节介绍的内容将会有很大帮助。

本书中有几部分用到了Java、Python和SQL的程序片段。使用Pig并非要求一定要了解这些语言,但是对于Pig的一些高级功能还是需要对Python和Java有所了解。有使用SQL背景的读者可以在1.1.2小节下面的“查询语言和数据流语言的比较”这一小节看到Pig Latin和SQL的相似和不同之处。本书中所使用的惯例

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

表明是新的术语、URL、电子邮件地址、文件名以及文件扩展名。等宽字体

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

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

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

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

警告这个图标表明是个警告或者警示。本书中的代码样例

本书中使用到的样例脚本、用户自定义函数(UDF)和数据集大多可以从我的GitHub资源库中下载。资源库中也包含了一些README文档,这些文档可以指导用户如何编译UDF并且帮助用户理解数据文件中的内容。文本中的每一个可以在GitHub中获取到的样例脚本,在开始的时候注释内容中都包含了文件名。Pig Latin样例脚本和Python样例脚本在examples目录下按章分类存放。用户自定义函数(UDF),包括使用Java编写的和使用Python编写的都放在另外一个目录udfs下。所有的数据集都放在data目录下。

为简明起见,每一个脚本都假定输入和输出都是本地文件目录。因此,当使用本地模式运行时,用户应该在需要输入的数据文件所在的目录下执行Pig脚本。而当在集群上运行时,用户需要将输入的数据文件放置在集群文件系统的用户根目录下。

本书提供的样例脚本都是在Pig 0.8.0版本或0.8.1版本下测试通过的,当然除了一些使用到0.9版本中新增功能的脚本,这些脚本是在0.9分支版本下测试通过的,因为在写本书的时候Pig还没正式发布0.9版本(译者注:Pig 0.9.2发行版对于这些新增功能也是适用的)。

样例中所使用的3个数据集虽然都相当小,但它们都是真实的数据集。文件名为baseball的文件包含的是棒球运动员的统计信息。第二个数据集是纽约股票交易数据,有两个文件,文件名分别是:NYSE_daily和NYSE_dividends。这份数据被简化为只包含2009年以后股票代码以C开头的数据信息,这是为了使数据量足够小以方便用户下载。当然,数据的模式并没有改变。如果用户想下载完整的数据集然后把它放到集群中(只需要几个节点就可以),那将是一个对Pig和Hadoop更加逼真的演示。在README文件中有如何下载这些数据集的说明。第三个数据集是从Pig官网的网页抓取的简单爬虫信息。

使用代码样例

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

虽然并非是必需的,但如果可以注明出处,我们将十分感激。出处一般包括书名、作者、出版商和ISBN。例如:“Programming Pig by Alan Gates (O’Reilly).Copyright 2011 Yahoo!, Inc., 978-1-449-30264-1.”

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

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

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

O’Reilly Media已经将本书上传到 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)

本书有一个Web页面,在此页面上我们列举了勘误表、例子和其他附加信息。用户可以通过如下链接访问这个页面:

http://shop.oreilly.com/product/0636920018087.do

可以通过如下E-mail地址将你对本书的评论或一些技术方面的问题发送给我们:

bookquestions@oreilly.com

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

http://www.oreilly.com鸣谢

一本书就像一支职业橄榄球队,大部分的荣耀都给了四分卫或跑卫。但是如果这个队防线很差,那么四分卫就不会有机会将球扔出去。接球员必须有能力接住球,防卫必须有能力阻止其他队得分。简而言之,整个队伍必须通力合作才能取胜。在这些背后在场地上还有一批教练、训练员以及准备和引导整个队伍的经理。这本书的形式也是同样的道理。书的封面上写的是我的名字,但是如果没有这群由开发者、研究者、测试者、文档书写者以及对Pig项目有贡献的人组成的了不起的团队,那将没什么有价值的信息来写成本书。

特别地,我想感谢Pig开发贡献者和使用者对于本书的贡献和反馈。Chris Olston、Ben Reed、Richard Ding、Olga Natkovitch、Thejas Nair、Daniel Dai和Dmitriy Ryaboy对本书一遍又一遍的草稿都提供了非常有帮助的反馈。Julien Le Dem提供了在Python中嵌入使用Pig的代码样例。Jeremy Hanna书写了Pig和Cassandra那个章节。她的反馈使本书的讲解更加清楚和正确。

还要感谢 Tom White在我下定决心写这本书时对我的鼓励,以及对于写这本书所需要的时间和努力所给予的理性的提醒。Hadoop项目的Chris Douglas在涉及Hadoop和MapReduce的章节给了我非常有帮助的反馈。

我还想感谢Mike Loukides和在O’Reilly的整个团队。他们让我觉得在写第一本书时是一段快乐的和令人愉悦的经历。最后,感谢Yahoo!培育了Pig以及投入了超过25个工程年(同时还在增加)的努力,同时让我有时间来写这本书。第1章初识Pig1.1 Pig是什么?

Pig提供了一个基于Hadoop的并行地执行数据流处理的引擎。它包含了一种脚本语言,称为Pig Latin,用来描述这些数据流。Pig Latin本身提供了许多传统的数据操作(如join、sort、filter等),同时允许用户自己开发一些自定义函数用来读取、处理和写数据。

Pig是一个Apache开源项目。这意味着用户可以免费下载源码或者二进制包,自由使用它,对这个项目贡献自己的代码,同时也可以在Apache License的许可范围下将Pig用到自己的产品中或者在需要的时候修改代码来满足特定需求。1.1.1 Pig是基于Hadoop的

Pig运行于Hadoop之上,它同时使用到Hadoop分布式文件系统HDFS和Hadoop处理系统MapReduce。

HDFS是一个分布式文件系统,它将文件存储到Hadoop集群的各个节点上。它负责将文件分割成许多数据块然后分发到不同的节点机器上,其中包括对每个数据块进行多份冗余备份,这样可以避免因为某台机器宕掉而造成数据丢失。HDFS提供了一种类似POSIX的用户交互形式给用户。默认情况下,Pig从HDFS中读取输入文件,使用HDFS来存放MapReduce任务所生成的中间数据,最终将输出写入HDFS中。在第11章,用户将看到Pig不只是可以从HDFS中读取输入文件或将输出文件写入HDFS的。

MapReduce是一个简单而强大的并行数据处理算法。MapReduce计算框架下的每个任务都由3个主要阶段组成:map阶段、shuffle阶段和reduce阶段。在map阶段,程序可以并行独立操作输入数据中的每一条记录。因为可以同时运行多个map任务,所以即使输入的数据量达到GB或者TB级别,只要有足够多的机器,map阶段通常在1分钟内就可以完成。

MapReduce任务的一个特别之处在于需要确定数据是根据哪个键进行收集的。例如,假设用户在处理一个网站的Web服务器日志,而且这个网站需要用户登录后才能操作,那么用户就可能会使用用户ID作为数据收集的键,因为通过这个用户ID就可以知道每个用户在这个网站上的对应的所有操作。map阶段后紧跟着就是shuffle阶段,在这个阶段数据已经根据用户指定的键收集起来并且分发到不同的机器上去了,这是为reduce阶段做准备。包含同一键的所有记录将会交由同一个reducer处理。

在reduce阶段,程序将提取每个键以及包含该键的所有记录。这个过程也是在多台机器上并行执行完成的。当处理完所有组时,reducer就可以写输出了。下面我们将通过一个简单的MapReduce程序进行演示。想更多地了解MapReduce是如何工作的,请看附录B“MapReduce介绍”。

MapReduce演示程序

假设现在有一个MapReduce程序对一个文本文件进行词频统计。该程序本身是MapReduce提供的演示程序。在这个例子中,map阶段会从文本文件中一次读取一行,然后分割出每个词作为一个字符串,之后对于分割出的每个单词,会输出单词本身以及数字1,数字1表示这个单词出现过1次。在shuffle阶段,将使用单词作为键,哈希分发对应的记录到不同的reducer中去。在reduce 阶段会将相同的单词对应的出现次数相加,并最终将求和后的数值和单词本身一起输出。以童谣“Mary Had a Little Lamb”为例,输入将是:Mary had a little lambits fleece was white as snowand everywhere that Mary wentthe lamb was sure to go.

这里假设每一行都被发送到不同的map任务中去了。当然事实上,每个map任务处理的数据要远远大于这个数量,这里只是为了后面更好地去描述。MapReduce整个过程的数据流如图1-1所示。

map阶段一旦结束,shuffle阶段将会把包含相同单词的所有记录提交到同一个reducer中。对于这个例子我们假设有两个reducer:以A~L开头的单词提交到第一个reducer中,而以M~Z开头的单词提交到第二个reducer中。这两个reducer最终将会把每个单词的出现次数分别相加然后输出。

Pig的所有数据处理过程都是使用MapReduce来执行的。Pig将用户所写的Pig Latin脚本编译成一个或者多个MapReduce任务,然后在Hadoop上执行。例子1-1展示了如何使用Pig Latin脚本来对童谣“Mary Had a Little Lamb”进行词频统计。图1-1 MapReduce执行过程图解例1-1 使用Pig对童谣“Mary和她的羔羊”进行词频统计--加载文件名为Mary的文件,--并将记录中的唯一字段命名为‘line’。input = load 'mary' as (line);--TOKENIZE将line按单词分割成列--flatten 接受TOKENIZE 操作后产生的记录集合然后分开成独立的列,-- 这个独立的列称为wordwords = foreach input generate flatten(TOKENIZE(line)) as word; -- 现在按照word进行分组grpd = group words by word; -- 计数cntd = foreach grpd gengerate group, COUNT(words); -- 打印结果dump cntd;

在使用Pig时无须去过度关注map、shuffle和reduce阶段,因为Pig会将脚本中的操作解析成相应的MapReduce阶段。1.1.2 Pig Latin,一种并行数据流语言

Pig Latin是一种数据流语言,这意味着它允许用户去描述如何从一个或多个数据源并行读取数据,然后并行地进行处理,最后将处理结果并行地输出到一个或多个结果集中。这些数据流可以像前面提到的那个词频统计例子一样是个简单的线性流。同时它们也可以是复杂的工作流,其中可以包含一些加入多个输入的节点,也可以包含一些将输入数据分割成多个流的节点,这些节点都是通过不同的操作符来处理的。用数学语言来描述的话,Pig Latin 描述的是一个有向无环图(DAG),在这个图中,节点代表处理数据的操作符,节点间的向量代表数据流。

这意味着Pig Latin和用户之前见过的许多编程语言会有所不同。在Pig Latin中没有if语句,也没有for循环操作。这是因为传统的过程语言和面向对象语言描述的是控制流,而数据流只处于一个从属地位。而Pig Latin更专注于数据流。想了解Pig Latin脚本中如何在处理数据流的同时加入控制流,请阅读第9章。

查询语言和数据流语言的比较

大体一瞥,人们会说Pig Latin不过是SQL的一个面向过程化的版本。尽管确实有一定的相似性,但是其实两者具有非常多的差异。SQL是一种查询语言,它关注于允许用户构造查询,它允许用户去描述他们想得到什么问题的答案,而不是如何给出问题的答案。然而在Pig Latin中,用户可以详细描述如何对输入的数据进行处理。

Pig Latin和SQL的另一个主要区别是SQL面向的是回答一个问题,因此当用户想同时进行多个数据操作时,他们要么使用多个查询语句,这时需要将一些查询的中间数据存放到临时表中;要么写一个大的包含子查询的查询语句,将一些初始的处理过程由子查询来完成。然而,很多用户发现子查询令人困惑而且也并非那么容易去构建。同时,子查询使用的是由内而外的设计,也就是说,在数据管道最里面的子查询会最先执行。

Pig被设计为实现知道将要进行的一系列的数据操作,因此不需要通过颠倒顺序的子查询的方式来写数据管道,也无需使用临时表来存放中间数据。这点将通过例子1-2和例子1-3来进行演示。

现在假设有个用户想先按某个键对表进行group分组操作,然后和第二张表进行join连接操作。在SQL查询中,因为join操作发生在group操作之后,所以要么使用子查询,要么写两个查询语句,同时将中间结果保存到临时表中。例子1-3用到了一个临时表,因为这样可读性要好些。例1-2 SQL中先进行分组然后进行连接操作CREATE TEMP TABLE t1 ASSELECT customer, sum(purchase) AS total_purchasesFROM transactionsGROUP BY customer;SELECT customer, total_purchases, zipcodeFROM t1, customer_profileWHERE t1.customer = customer_profile.customer;

在Pig Latin中,是另外一种方式,如例1-3所示。例1-3 Pig Latin中先进行分组然后进行连接操作-- 加载汇报文件,按照customer字段进行分组,然后计算他们的总购物金额txns = load 'transactions' as (customer, purchase);grouped = group txnx by customer;total = foreach grouped generate group, SUM(txns.purchase) as tp;-- 加载 customer_profile 文件profile = load 'customer_profile'as (customer, zipcode);-- 对已经分好组并进行了累加计算的汇报文件数据和customer_profile文件进行连接answer = join total by group, profile by customer;-- 将结果输出到控制台dump answer;

此外,SQL和Pig Latin各因不同的应用场景而生。SQL的应用场景是RDBMS,在这种场景下,数据是标准化的,并且加上了模式和其他一些特有的约束(例如,null值也是不可以脱离约束单独存在的等)。Pig是为Hadoop数据处理环境而设计的,在这种环境下,模式有时是未知的或不一致的,数据可能没有进行恰当的约束而且很少进行数据标准化。基于这些不同,Pig不需要将数据事先导入表中,当数据导入HDFS中后,它就可以直接操作这些存放在HDFS的数据。

如果语言和文化类似,那么融入一个新的环境可能会更加容易些。我和妻子一起去过法国几次。我会讲很少的法语,但是因为是商业语言(或许是因为美国人和大不列颠人喜欢到法国度假),对于我来说法语中已经包含了足够多的英语口语,使我足够应付得了。而我的妻子,她会讲法语。她在法国有朋友去拜访时,她可以和他们很好地交谈。她可以去那些不在通常的旅游线路上的其他景区探险。她的法国经历比我要多得多,因为她会讲当地本土语言——法语。

在数据处理范畴里,SQL就是英语。它有个非常好的特点就是无论是人还是工具都认识它,也就是说它的入门门槛很低。我们的目标是使Pig成为像Hadoop这样的并行数据处理系统范畴里的母语。尽管这可能要求用户需要进行一定的学习才能使用,但是它可以让用户更加充分地利用Hadoop提供的计算能力。

Pig和MapReduce的区别是什么

我刚刚声明Pig团队的一个目标是使Pig Latin成为像Hadoop这样的并行数据处理环境的母语。但是难道MapReduce提供的还不够吗?有必要使用Pig吗?

Pig比直接使用MapReduce有几个优点。Pig Latin 提供了所有标准的数据处理操作,例如join、filter、group by、order by、union等。MapReduce直接提供了group by操作(也就是shuffle和reduce两个阶段做的事情),同时通过实现分组操作间接地提供了order by 操作。过滤器操作和推测执行操作可以在map阶段进行简单实现。但是其他的操作,特别是join操作无法提供,所以必须由用户自己进行代码实现。

Pig提供了一些对这些标准的数据操作的复杂的、完备的实现。例如,因为每个键对应的记录的个数很少是均匀地分布在集群中的,所以提交给reducer的数据经常会产生数据倾斜。也就是说,有的reducer需要比别的reducer处理10倍或更多倍的数据。Pig具有join和order by 操作可以处理这种情况,而且(在一些情况下)可以重新均衡reducer负荷。这些需要Pig团队花费好几个月的时间编写MapReduce程序,然后再重构代码,这确实耗费时间。

在MapReduce中,在map阶段和reduce阶段的内部的数据处理对于系统来说是不透明的。这意味着MapReduce没有机会优化或者检查用户的代码。Pig另一方面,可以通过分析Pig Latin脚本来了解用户描述的数据流。这意味着Pig可以在早期进行错误检查(例如用户是否将一个string类型的字段放到一个integer类型的字段中?)和进行优化(例如这两个group操作是否可以合并?)

MapReduce没有一个类型系统,这是有意这么设计的,因为这样可以给用户更大的自由度去使用他们自己的数据类型和序列化框架。但这样就产生了一个不好的问题,就是限制了系统在运行前和运行时对用户代码进行检查的能力。

这几个方面都表明Pig Latin相对于MapReduce Java代码更容易编写和维护。我做了一个并非科学的实验,对于同一个操作我分别使用Pig Latin和MapReduce进行实现。假设有个文件存有用户数据,另一文件存放了对于某个网站的点击数据,例子1-4所示的Pig Latin脚本将找到年龄为18~25岁的用户访问最多的5个页面。例1-4 查找访问次数最多的前5个URLUsers = load 'users' as (name, age);Fltrd = filter Users by age >= 18 and age <=25;Pages = load 'pages' as (user, url);Jnd = join Fltrd by name, Pages by user;Grpd = group Jnd by url;Smmd = foreach Grpd generate group, COUNT(Jnd) as clicks;Srtd = order Smmd by clicks desc;Top5 = limit Srtd 5;store Top5 into 'top5sites';

这段脚本的第1行表示加载文件名为users的文件,同时声明这份数据有两个字段:name和age,而且为这个输入取别名为Users。第2行是个过滤器,将Users中age这个字段值大于等于18而且小于等于25的记录过滤出来,不满足条件的数据将被忽略。经过过滤器后,留下的数据就是在我们感兴趣的年龄范围内的了。我们将这个过滤器的结果取别名为Fltrd。

第3行是第2个load加载数据语句,这个语句加载了文件Pages,并取别名为Pages,它声明了两个字段:user和url。

“Jnd = join”这一行以Fltrd.name和Pages.user为键,对Fltrd和Pages进行join连接操作。通过这次join操作我们就可以得到每个用户访问过的所有URL链接了。

“Grpd = group”这一行按照URL进行分组。结果是每一个url,例如pignews.com/frontpage,都对应着一组url字段中包含了对应值的所有记录。紧跟着的下一行会统计每个URL对应的记录个数。这一行后我们就知道了,对于每个URL,被年龄为18~25岁的用户访问了多少次。

之后的一件事就是按访问次数从访问最多到访问最少进行排序。“Srtd = order”这一行就是根据前一行的统计结果进行desc(降序)排列。因此,最大值将在第1行。因为最终我们只需要最前面的5条记录,所以最后一行将统计结果限制在前5行。最后的结果重新存放到HDFS中一个叫做top5sites的文件中。

在Pig Latin中整个处理过程需要写9行代码,耗时在15分钟左右,其中包括写代码和对代码进行调试的时间。如果以MapReduce(这里省略了)来写的话,需要差不多170行的代码而且花费了我4个小时的时间才调试成功。Pig Latin同样利于维护,因为这段代码,对于后来的其他开发者同样是容易理解和方便修改的。

当然Pig所带来的这些便利同样是有代价的。通过MapReduce框架可以开发一些算法,在Pig中却很难实现。同时对于开发者,他们需要放弃一个层次的控制权。一名优秀的工程师,只有给予足够的时间,总是可以将一个普通的系统做得足够好。因此对于不常见的算法或者是对于性能要求很高的话,这种情况下使用MapReduce仍然是正确的选择。基本上这种情况也和选择Java编码而不选择使用像Python这样的脚本语言的情形是一样的。Java功能强大,但是因为它是高级程序语言,所以使用它开发需要比脚本语言花费更多的时间。开发者需要根据实际情况选择合适的工具。1.1.3 Pig的用途

以我的经验,Pig Latin的使用场景可以分为独立的三大类:传统的抽取转换加载(ETL)数据流、原生数据研究和迭代处理。

最大的使用场景就是数据流了。一个通常的例子就是网络公司从他们的Web服务器上收集到日志,进行数据清洗,之后进行简单的聚合预计算,然后导入数据仓库中。在这种情况下,数据被加载到计算网格中,之后使用Pig从数据泥潭中清理出有价值的数据。同时还可以使用Pig将用户网页操作数据和用户数据库信息进行join连接,这样可以将用户cookie和已知的用户信息关联起来。

另外一个数据流应用的例子是使用Pig处理离线数据来建立用户行为预测模型。Pig被用来扫描所有的用户和网站的交互数据,最终将用户分为各种各样的群组。然后,对于每个群组会生成一个数学模型,根据该模型可以预知这个群组的用户对各种类型的广告或者新闻文章的反映是什么样子的。通过这种方式,网站可以知道展示什么样的广告可以更有可能获得更多的点击,或者发布什么样的新闻故事可以更有可能吸引用户和挽留用户再次访问。

传统上,使用像SQL这样的语言执行点对点的查询可以快速地为问题准备好相应的数据。然而,对于原始数据的研究,一些用户还是偏向使用Pig Latin脚本。因为Pig可以在无模式,模式信息不全,或者模式不一致的情况下进行操作,同时因为Pig可以很容易地控制封装的数据,因此对于那些期望在数据没有进行清洗也没有写入数据仓库的情况下,分析数据的研究人员经常更偏好于使用Pig。经常处理大规模数据集的研究人员经常会使用像Perl或者Python这样的脚本语言进行处理。具有这些使用背景的用户通常更喜欢使用Pig这样的数据流范式而非像SQL那样的声明式查询语言。

创建迭代处理模型的用户也开始使用Pig。假设有一个新闻门户网站,它保留了一个它跟踪的关于该网站的所有新闻故事的图。在这个图中每个新闻故事都是一个节点,节点间的连线表示的是相关故事间的关系。例如,所有关于即将来临的选举的故事都是联系到一起的。每5分钟都有一组新的故事进来,这时数据处理引擎需要将这组故事增加到图中。这些故事中有一些是新的,有一些是对之前的故事进行的更新,还有一些是替代之前已经存储的一些故事的。这时需要对整个故事图做一些数据处理步骤。例如,对于建立行为目的模型的处理过程就需要将用户数据和整个故事图进行连接。每5分钟重新运行整个图是不可行的,因为对于适当数量的硬件资源来说在5分钟内运行出结果是不可能的。但是模型创建者不想只是每天更新一次这些模型,因为那意味着会错过一整天的时间来提供机会。

为了应付这个问题,有必要定期地首先对整个图进行连接,例如可以按照天来进行连接。然后,每5分钟一旦有数据进来,就可以立即完成对新进来的数据进行连接操作,同时这个结果是可以和对整个图做连接的结果整合在一起的。这个组合步骤并不容易,因为需要在5分钟内完成对整个图进行插入、更新和删除操作。使用Pig Latin来表达这种组合关系是可以的并且是相当方便的。

目前所说的一切都隐含着一点:Pig(与MapReduce一样)是面向数据批处理的。如果需要处理的是GB或者TB数量级的数据,那么Pig是个不错的选择。但是因为它期望的是序列地读取一个文件中的所有记录然后序列地将输出写入存储中,因此对于那些需要写单条或者少量记录,或者查询随机序列下的多条不同记录这样的任务,Pig(与MapReduce一样)并非是个好选择。关于在这些情况下选用什么样的软件才是合理的更多讨论请查看第12.3节“NoSQL数据库”。1.1.4 Pig的设计思想

在早期,作为潜在贡献者加入Pig项目的人们并非了解这个项目究竟是关于什么的。他们并不清楚怎样做才是最好的贡献或者哪些贡献会被接受以及哪些不会被接受。因此,Pig团队发布了一个项目设计思想声明,其内容总结为Pig渴望成为:

Pig什么都吃

不管数据是否有元数据,Pig都可以操作。不管数据是关系型的、嵌套型的,或者是非结构化的,Pig也同样可以操作。而且它还可以很容易地通过扩展,不单单可以操作文件,还可以操作key/value型的存储,以及数据库等。

Pig无处不在

Pig期望成为一种并行数据处理语言。它不会局限于是一种特殊的并行处理框架。它首先是基于Hadoop之上的实现,但是我们期望它并非只能在Hadoop平台上使用。

Pig是家畜

Pig被设计为可以让用户很容易地控制和修改的语言。

Pig允许用户随时整合加入他们的代码,因此目前它支持用户自定义字段类型转换函数、用户自定义聚合方法函数和用户定义条件式函数。这些函数可以使用Java来写也可以使用最终可以编译成Java代码的脚本语言(例如Jython)编写。Pig支持用户定义的加载和存储函数。Pig通过自己的stream 命令和需要MapReduce相关的JAR包的mapreduce命令可以执行外部的执行命令。Pig同样允许用户为自己的特定使用场景提供一个用户自定义的分区方法函数,使他们执行的任务在reduce阶段可以达到一个均衡的负荷。

Pig有一个优化器,它可以将Pig Latin脚本中的操作过程进行重新排列以达到更好的性能,例如将MapReduce任务进行合并等。但是,如果对于某种情形下这种优化是不必要的话,用户可以很容易地将最优控制器关闭,这样执行过程就不会发生改变。

Pig会飞

Pig处理数据很快。我们会持续地优化性能,同时不会增加一些使Pig显得较重而降低性能的新功能。1.2 Pig发展简史

Pig最初是作为Yahoo!的一个探索性的项目,Yahoo!的科学家们设计了Pig并且给出了一个原型实现。正如2008年发表在数据管理[1]专业委员会(SIGMOD})杂志的一篇论文所描述的,研究者认为Hadoop所描述的MapReduce框架“过于底层和严格,需要用户花费大量时间编写代码,而且很难维护和重用。”同时他们注意到MapReduce用户对像SQL这样的声明式语言并不熟悉。因此他们着手开发“一种叫做Pig Latin的新语言,这种语言被设计为在像SQL这样的声明式类型的语言和像MapReduce这种较底层的过程式的语言之间达到一个非常好的平衡点。”

最初Yahoo!的Hadoop使用者开始采用Pig。之后一个开发工程师团队开始接手Pig的最初原型并将Pig原型开发成一个达到产品级别的可用产品。在这个时间点左右,也就是2007年的秋天,Pig通过Apache孵化器进行开源。一年后也就是2008年的9月,Pig的第一个发布版本出现了。同年的晚些时候,Pig从孵化器中毕业,正式提升为Apache Hadoop项目的一个子项目。

2009年早期其他公司在他们的数据处理中开始使用Pig。Amazon也将Pig加入它的弹性MapReduce服务中的一部分。2009年末,Yahoo!公司所运行的Hadoop任务有一半是Pig任务。在2010年,Pig发展持续增长,这一年Pig从Hadoop的子项目中脱离出来,自己成为了一个最高级别的Apache项目。为什么叫做Pig

有一个问题经常被问起,那就是“为什么把它命名为Pig?”人们还想知道是否Pig这个词是由缩写字母组成的。回答是否定的。事实上最初开发这个项目的研究人员只是简单地把它称为“那种语言。”不过他们终究需要为它起个名字。一名研究人员的脑海中出现了Pig这个单词,然后就提议称它为Pig,这个名字一下子就让大家惊住了。这个名字古怪但是容易记也容易读。虽然有些人暗示这个名字听起来有点别扭或者傻,但是因这个名字促使了我们一个非常不错的命名方法,例如把这种语言命名为Pig Latin,把终端交互命名为Grunt,把一个共享资源库性质的分支成为Piggybank。

[1] Christopher Olston et al, “Pig Latin: A Not-So-Foreign Language for Data Processing,”可以通过如下链接获得http://portal.acm.org/citation.cfm?id=1376726。第2章安装和运行Pig2.1 下载和安装Pig

用户需要下载和安装Pig,才能在本地机器或者Hadoop集群上使用它。如果用户已经了解并完成了这一操作,那么可以直接跳到2.2节“运行Pig”进行阅读。

用户既可以直接下载Pig安装包也可以先下载源代码然后自行进行编译。当然同样也可以以Hadoop分支的方式获得Pig。2.1.1 从Apache下载Pig软件包

这个是Apache Pig的官方版本。它是一个软件包,里面包含了运行Pig所需的所有JAR包。用户可以通过访问Pig发布页面进行下载。

Pig不需要安装到Hadoop集群中去。它运行在用户提交Hadoop任务的那台机器上。尽管用户可以从个人笔记本电脑或者台式计算机运行Pig,但是在实际操作中,大部分的集群管理员会配置好一到多台可以访问他们Hadoop集群的服务器,虽然这些服务器可以不是集群的一部分(也就是说它们既不是数据节点也不是计算节点)。通过这种方式,管理员可以方便地升级Pig和将工具集成在一起,同时也可以很好地限制人员对于集群的访问。这些机器被称为网关机或者缝边机。本书中我称之为网关机。

用户需要在这些网关机上安装Pig。如果用户是通过个人台式计算机或者笔记本电脑访问Hadoop集群的话,那么同样需要在个人台式计算机或者笔记本电脑上安装Pig。当然,如果用户想通过本地模式使用Pig的话,那么也可以将Pig安装到个人的本地机器上。

Pig的核心是用Java语言编写的,因此它是跨平台的。启动Pig的shell脚本是个bash脚本,所以它需要一个Unix环境。Pig所基于的Hadoop,即使使用的是本地模式,也需要是UNIX环境的,因为Hadoop的文件操作是基于UNIX的。实际情况是,大部分的Hadoop集群采用的是Linux系统。很多Pig开发者是在Mac OS X系统上开发和测试Pig的。

Pig需要Java 1.6支持,Pig版式从0.5到0.9需要Hadoop 0.20版本支持。对于以后的版本,请在下载页面确认该版本需要对应的Hadoop版本是多少。下载的Pig中会包含与它对应的Hadoop。如果用户想在本地模式下使用Pig或者想把它安装到一个没有安装Hadoop的网关机上,那么就不需要额外去下载Hadoop。

一旦下载完Pig,可以把它放在自己喜欢的任何位置,Pig无需依赖一个特定位置。安装第一步,将压缩包放在用户期望的目录下然后执行:tar xzf filename

其中filename 是用户所下载的TAR压缩包文件。

安装第二步是确定环境变量JAVA_HOME是否设置指向到包含一个Java发布版的目录,这一步是为执行Pig做环境准备。如果这个环境变量没有设置,那么Pig会立即执行失败。用户可以通过shell命令设置该环境变量,也可以在调用Pig的时候通过命令行指定该环境变量,或者在位于用户刚才解压后的文件bin目录下的pig脚本文件中显式地指定好JAVA_HOME环境变量。用户可以通过执行 which java命令查看当前java所在路径,把这条命令返回的结果后面的bin/java 去掉,就是当前环境中JAVA_HOME的值。2.1.2 从Cloudera下载Pig

除了官方的Apache版本之外,同样有一些其他的公司会重新包装和分发Hadoop以及与其相关的工具。当前这些公司中最受欢迎的是Cloudera,它为Red Hat系列的系统开发相应的RPM包以及为Debian系统开发相应的APT包。对于不可以使用这些包管理器的其他系统,Cloudera同样提供了tar压缩包文件。使用像Cloudera这样的发行版的一个优点是与Hadoop相关的所有工具都是打包在一起并且在一起测试完成的。同样,如果用户需要专业的技术支持,它也是提供的。缺点是用户将受制于其使用的发行版的提供商的发行速度。Apache推出一个新版本后,然后到各个分支给出不同的发行版,这中间会有一定的时间延迟。

如果想获得从Cloudera下载和安装Hadoop和Pig的详细说明,请访问Cloudera下载页面。需要注意的是用户需要单独下载Pig,因为Hadoop包中没有包含Pig。2.1.3 使用Maven下载Pig

除了可以从Pig的Apache官方网站上下载发行版之外,用户还可以通过Apache的Maven资源库下载Pig。这个站点包含了Pig需要的所有JAR文件,包括源代码jar包文件,Javadocs jar包文件,同时还包括一个定义了Pig所依赖的JAR包的POM文件。如果用户使用maven或者ant进行编译,在编译过程中也会自动从这个资源库中下载相关的JAR包。2.1.4 下载Pig源码

当用户从Apache下载Pig的时候,同时也会得到所有Pig的源代码。这样可以方便用户调试其下载的那个版本的Pig或者只是下载代码下来看看Pig是如何工作的。但是如果用户想一直跟随在最前沿,想在正式版本发行前尝试新的功能或者进行bug修复,那么可以通过Apache的版本管理资源库中下载源代码。用户需要可以访问Pig的问题跟踪系统并将一些补丁文件打到自己使用的版本中,这些补丁文件往往还没有来得及合并到代码资源库中。如何通过svn或者git获得Pig可以在Pig的版本控制页面这个网页看到。2.2 运行Pig

用户可以在本地运行Pig也可以在集群系统上运行Pig,还可以将Pig作为Amazon的弹性MapReduce服务系统的一个组成部分运行。2.2.1 本地单机运行Pig

本地单机运行Pig按Pig的定义说法是以local模式运行。Local模式对于样机研究和调试用户所写的Pig Latin脚本是非常有用的。有些人在处理小文件的时候也采用这种模式,尽快处理流程和处理大数据量是相同的——这样可以保证无论处理什么数量级别的数据时都采用一致的数据流,但是他们不希望集群为处理小的文件和小的任务而浪费资源。

在0.6版本和更早的版本中,Pig自身是以local本地模式执行脚本的。从版本0.7开始,它开始使用Hadoop的类 LocalJobRunnr,这个类可以读取本地文件系统并且可以在本地执行MapReduce任务。这样执行的优点是在本地运行Pig任务和在集群中执行是相同的,同时它们都是以相同的流程执行,从而使得调试更加方便。缺点是太慢,启动一个本地的Hadoop实例需要将近20秒的时间,即使是非常小的[1]任务也需要耗时这么久。

下面我们以local本地模式运行一个Pig Latin脚本。查看前言的“本书中的代码样例”部分获得如何下载本例中所需要的数据和Pig Latin代码样例脚本源码。例2-1所示是个简单的例子,其加载了文件NYSE_dividends,并按股票交易码进行分组,然后计算每个交易码对应的平均股息。例2-1 以本地模式运行Pig-- average_dividend.pig-- 从NYSE_dividends中加载数据,并声明其有4个字段dividends = load 'NYSE_dividends' as (exchange, symbol, date, dividend);-- 按照股票交易号对行进行分组grouped = group dividends by symbol;-- 计算每个股票交易号对应的平均股息avg = foreach grouped generate group, AVG(dividends.dividend);-- 将结果存储到文件average_dividend中store avg into 'average_dividend';

如果用户使用 head -5 这个shell命令来查看NYSE_dividends文件,那么将会看到:NYSE CPO 2009-12-30 0.14NYSE CPO 2009-09-28 0.14NYSE CPO 2009-06-26 0.14NYSE CPO 2009-03-27 0.14NYSE CPO 2009-01-06 0.14

这与我们在Pig Latin脚本中所声明的结构是一致的。第1个字段是这支股票所属的交易所的名称,第2个字段是股票交易码,第3个字段是所支付股息的日期,第4个字段是股息的大小。

提示记住,在运行Pig前用户需要设置JAVA_HOME环境变

量。

这个值等于用户使用的Java发行版所在的目录路径。

切换到NYSE_dividends文件所在的目录,然后用户就可以通过如下方式以本地模式的方式运行Pig了:pig_path/bin/pig –x local average_dividend.pig

其中pig_path是指用户本地机器Pig安装所在的目录。

执行上述命令后用户应该能看到屏幕上有很多输出。大部分输出是MapReduce的LocalJobRunner所生成的日志,但其中也有一些是Pig告诉用户它将如何执行这个脚本,以及执行过程中的状态信息等。在输出的最底端用户应该能看到一个简短的提示信息 Success!。这意味着一切进展顺利。该脚本将输出存储到average_dividend文件中,因此也许用户期望能在自己的本地目录下发现一个名字为average_dividend的文件。事实上用户会发现一个这个名字的目录,该目录下有一个名字为part-r-00000的文件。这是因为Hadoop是一个分布式系统,一般是以并行的方式处理数据的,当它将输出数据存放到一个“文件”中的时候,它就会使用这个“文件”的名称创建一个目录,每一个写处理过程就会在这个文件夹中生成一个独立的文件片段。在这个例子中我们只有一个写处理过程,因此我们只得到了一个文件片段。用户可以通过如下命令查看这个结果文件中的内容:cat average_dividend/part-r-00000 | head -5

结果是:CA 0.04CB 0.35CE 0.04CF 0.1CI 0.042.2.2 在Hadoop集群上运行Pig

大部分的时间用户将在Hadoop集群上运行Pig。正如我们在2.1节“下载和安装Pig”中所描述的那样,Pig可以在用户个人机器或者网关机上以local本地模式运行。所有的语法解析、执行校验以及制定执行计划都是在本地完成的。Pig然后才会在集群上执行MapReduce任务。

提示当我提到“用户的网关机”的时候,我的意思是那台用

户可以提交Pig任务的机器。通常情况是一台或多台可以访

问Hadoop集群的机器。然后,看用户机器的配置了,它也

可以是用户的本地机器。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书

若在网站上没有找合适的书籍,可联系网站客服获取,各类电子版图书资料皆有。

客服微信:xzh432

登入/注册
卧槽~你还有脸回来
没有账号? 忘记密码?