云计算PIG的使用_第1页
云计算PIG的使用_第2页
云计算PIG的使用_第3页
云计算PIG的使用_第4页
云计算PIG的使用_第5页
已阅读5页,还剩56页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

-.z.云计算pig使用Hadoop的普及和其生态系统的不断壮大并不令人感到意外。Hadoop不断进步的一个特殊领域是Hadoop应用程序的编写。虽然编写Map和Reduce应用程序并不十分复杂,但这些编程确实需要一些软件开发经历。ApachePig改变了这种状况,它在MapReduce的根底上创立了更简单的过程语言抽象,为Hadoop应用程序提供了一种更加接近构造化查询语言(SQL)的接口。因此,您不需要编写一个单独的MapReduce应用程序,您可以用PigLatin语言写一个脚本,在集群中自动并行处理与分发该脚本。

PigLatin例如让我们从一个简单的Pig例如开场介绍,并剖析该例如。Hadoop的一个有趣的用法是,在大型数据集中搜索满足*个给定搜索条件的记录〔在Linu*®中被称为grep〕。清单1显示了在Pig中实现该过程的简单性。在所显示的三行代码中,只有一行是真正的搜索。第一行只是将测试数据集〔消息日志〕读取到代表元组集合的包中。用一个正则表达式来筛选该数据〔元组中的惟一条目,表示为$0或field1〕,然后查找字符序列WARN。最后,在主机文件系统中将这个包存储在一个名为warnings的新文件中,这个包现在代表来自消息的包含WARN的所有元组。清单1.一个简单的PigLatin脚本

messages=LOAD'messages';

warns=FILTERmessagesBY$0MATCHES'.*WARN+.*';

STOREwarnsINTO'warnings';

如您所见,这个简单的脚本实现了一个简单的流,但是,如果直接在传统的MapReduce模型中实现它,则需要增加大量的代码。这使得学习Hadoop并开场使用数据比原始开发容易得多。现在让我们更深入地探讨Pig语言,然后查看该语言的一些功能的其他例如。

--------------------------------------------------------------------------------

回页首

PigLatin的根底知识

PigLatin是一个相对简单的语言,它可以执行语句。一调语句就是一个操作,它需要输入一些内容〔比方代表一个元组集的包〕,并发出另一个包作为其输出。一个包就是一个关系,与表类似,您可以在关系数据库中找到它〔其中,元组代表行,并且每个元组都由字段组成〕。用PigLatin编写的脚本往往遵循以下特定格式,从文件系统读取数据,对数据执行一系列操作〔以一种或多种方式转换它〕,然后,将由此产生的关系写回文件系统。您可以在清单1中看到该模式的最简单形式〔一个转换〕。

Pig拥有大量的数据类型,不仅支持包、元组和映射等高级概念,还支持简单的数据类型,如int、long、float、double、chararray和bytearray。如果使用简单的类型,您会发现,除了称为bincond的条件运算符〔其操作类似于Cternary运算符〕之外,还有其他许多算术运算符〔比方add、subtract、multiply、divide和module〕。并且,如您所期望的那样,还有一套完整的比拟运算符,包括使用正则表达式的丰富匹配模式。所有PigLatin语句都需要对关系进展操作〔并被称为关系运算符〕。正如您在清单1中看到的,有一个运算符用于从文件系统加载数据和将数据存储到文件系统中。有一种方式可以通过迭代关系的行来FILTER数据。此功能常用于从后续操作不再需要的关系中删除数据。另外,如果您需要对关系的列进展迭代,而不是对行进展迭代,您可以使用FOREACH运算符。FOREACH允许进展嵌套操作,如FILTER和ORDER,以便在迭代过程中转换数据。

ORDER运算符提供了基于一个或多个字段对关系进展排序的功能。JOIN运算符基于公共字段执行两个或两个以上的关系的内部或外部联接。SPLIT运算符提供了根据用户定义的表达式将一个关系拆分成两个或两个以上关系的功能。最后,GROUP运算符根据*个表达式将数据分组成为一个或多个关系。表1提供了Pig中的局部关系运算符列表。表1.PigLatin关系运算符的不完整列表运算符描述

FILTER基于*个条件从关系中选择一组元组。

FOREACH对*个关系的元组进展迭代,生成一个数据转换。

GROUP将数据分组为一个或多个关系。

JOIN联接两个或两个以上的关系〔内部或外部联接〕。

LOAD从文件系统加载数据。

ORDER根据一个或多个字段对关系进展排序。

SPLIT将一个关系划分为两个或两个以上的关系。

STORE在文件系统中存储数据。虽然这不是一个详尽的PigLatin运算符清单,但该表提供了一套在处理大型数据集时非常有用的操作。您可以通过参考资料了解完整的PigLatin语言,因为Pig有一套不错的在线文档。现在尝试着手编写一些PigLatin脚本,以了解这些运算符的实际工作情况。

--------------------------------------------------------------------------------

回页首获得Pig

在有关Hadoop的早期文章中,我采用的方法是将Hadoop安装和配置为一个软件包。但Cloudera通过用Linu*将它打包为一个虚拟设备,使得Hadoop更易于使用。虽然它是一个较大的下载,但它已预建立并配置了虚拟机(VM),其中不仅有Hadoop,还包括了ApacheHive和Pig。因此,利用一个下载和免费提供的2型虚拟机管理程序〔VirtualBo*或基于内核的虚拟机[KVM]〕,您便可以拥有预配置的、已准备就绪的整个Hadoop环境。

--------------------------------------------------------------------------------

回页首让Hadoop和Pig启动并运行下载完您的特定虚拟机文件之后,需要为您的特定虚拟机管理程序创立一个VM。在参考资料中,您可以找到该操作的分步指南。

ClouderaVM内存我发现,仅为虚拟机分配1GB的内存时,它无法正常工作。将该内存分配提高至两倍甚至三倍时,它才能够正常运行〔也就是说,不会出现Java™堆内存的问题〕。一旦创立了自己的VM,就可以通过VirtualBo*来启动它,VirtualBo*引导Linu*内核,并启动所有必要的Hadoop守护进程。完成引导后,从创立一个与Hadoop和Pig通信的终端开场相关操作。您可以在两种模式中任选一种来使用Pig。第一种是Local〔本地〕模式,它不需要依赖Hadoop或Hadoop分布式文件系统(HDFS),在该模式中,所有操作都在本地文件系统上下文中的单一Java虚拟机(JVM)上执行。另一种模式是MapReduce模式,它使用了Hadoop文件系统和集群。

Local模式的Pig

对于Local模式,只需启动Pig并用e*ectype选项指定Local模式即可。这样做可以将您带入Grunt外壳,使您能够以交互方式输入Pig语句:

$pig-*local

...

grunt>

在这里,您能够以交互方式编写PigLatin脚本的代码,并查看每个运算符后面的结果。返回清单1,并尝试使用这个脚本〔参见清单2〕。注意,在这种情况下,不需要将数据存储到*个文件中,只需将它转储为一组关系。您可能会在修改后的输出中看到,每个日志行〔与FILTER定义的搜索条件相匹配〕本身就是一个关系〔以括号[()]为界〕。清单2.在Local模式中以交互方式使用Pig

grunt>messages=LOAD'/var/log/messages';

grunt>warns=FILTERmessagesBY$0MATCHES'.*WARN+.*';

grunt>DUMPwarns

...

(Dec1003:56:43localhostNetworkManager:<WARN>nm_generic_enable_loopback():error...

(Dec1006:10:18localhostNetworkManager:<WARN>check_one_route():(eth0)error...

grunt>

如果您已经指定STORE运算符,则它会在一个指定名称的目录〔而不是一个简单的常规文件〕中生成您的数据。

Mapreduce模式中的Pig

对于MapReduce模式,必须首先确保Hadoop正在运行。要做到这一点,最简单的方法是在Hadoop文件系统树的根上执行文件列表操作,如清单3所示。清单3.测试Hadoop可用性

$hadoopdfs-ls/

Found3items

drw*rw*rw*

-hue

supergroup

02011-12-0805:20/tmp

drw*r-*r-*

-hue

supergroup

02011-12-0805:20/user

drw*r-*r-*

-mapredsupergroup

02011-12-0805:20/var

$

如清单3所示,如果Hadoop成功运行,此代码的结果会是一个或多个文件组成的​​列表。现在,让我们来测试Pig。从启动Pig开场,然后将目录更改为您的HDFS根,以确定在HDFS中是否可以看到外部所看到的结果〔参见清单4〕。清单4.测试Pig

$pig

2011-12-1006:39:44,276[main]INFO

org.apache.pig.Main-Loggingerrormessagesto...

2011-12-1006:39:44,601[main]INFO

org.apache.pig....Connectingtohadoopfile\

systemat:hdfs://:8020

2011-12-1006:39:44,988[main]INFO

org.apache.pig....connectingtomap-reduce\

jobtrackerat::8021

grunt>cdhdfs:///

grunt>ls

hdfs:///tmp

<dir>

hdfs:///user

<dir>

hdfs:///var

<dir>

grunt>

到目前为止,一切都很好。您可以在Pig中看到您的Hadoop文件系统,所以,现在请尝试从您的本地主机文件系统将一些数据读取到HDFS中。可以通过Pig将*个文件从本地复制到HDFS〔参见清单5〕。清单5.获得一些测试数据

grunt>mkdirtest

grunt>cdtest

grunt>copyFromLocal/etc/passwdpasswd

grunt>ls

hdfs:///test/passwd<r1>1728

接下来,在Hadoop文件系统中测试数据现在是平安的,您可以尝试另一个脚本。请注意,您可以在Pigcat文件,查看其内容〔只是看看它是否存在〕。在这个特殊例如中,将确定在passwd文件中为用户指定的外壳数量〔在passwd文件中的最后一列〕。要开场执行该操作,需要从HDFS将您的passwd文件载入一个Pig关系中。在使用LOAD运算符之前就要完成该操作,但在这种情况下,您可能希望将密码文件的字段解析为多个独立的字段。在本例中,我们指定了PigStorage函数,您可以使用它来显示文件的分隔符〔本例中,是冒号[:]字符〕。您也可以用AS关键字指定独立字段〔或架构〕,包括它们的独立类型〔参见清单6〕。清单6.将文件读入一个关系中

grunt>passwd=LOAD'/etc/passwd'USINGPigStorage(':')AS(user:chararray,\

passwd:chararray,uid:int,gid:int,userinfo:chararray,home:chararray,\

shell:chararray);

grunt>DUMPpasswd;

(root,*,0,0,root,/root,/bin/bash)

(bin,*,1,1,bin,/bin,/sbin/nologin)

...

(cloudera,*,500,500,,/home/cloudera,/bin/bash)

grunt>

接下来,使用GROUP运算符根据元组的外壳将元组分组到该关系中〔参见清单7〕。再次转储此关系,这样做只是为了说明GROUP运算符的结果。注意,在这里,您需要根据元组正使用的特定外壳〔在开场时指定的外壳〕对元组进展分组〔作为一个内部包〕。清单7.将元组分组为其外壳的一个函数

grunt>grp_shell=GROUPpasswdBYshell;

grunt>DUMPgrp_shell;

(/bin/bash,{(cloudera,*,500,500,,/home/cloudera,/bin/bash),(root,*,0,0,...),...})

(/bin/sync,{(sync,*,5,0,sync,/sbin,/bin/sync)})

(/sbin/shutdown,{(shutdown,*,6,0,shutdown,/sbin,/sbin/shutdown)})

grunt>

但是,您想要的是在passwd文件中指定的独特外壳的计数。所以,需要使用FOREACH运算符来遍历分组中的每个元组,COUNT出现的数量〔参见清单8〕。清单8.利用每个外壳的计数对结果进展分组

grunt>counts=FOREACHgrp_shellGENERATEgroup,COUNT(passwd);

grunt>DUMPcounts;

...

(/bin/bash,5)

(/bin/sync,1)

(/bin/false,1)

(/bin/halt,1)

(/bin/nologin,27)

(/bin/shutdown,1)

grunt>

备注:如果要将该代码作为一个脚本来执行,只需将脚本输入到*个文件中,然后使用pigmyscript.pig来执行它。

--------------------------------------------------------------------------------

回页首诊断运算符

Pig支持大量诊断运算符,您可以用它们来调试Pig脚本。正如您在之前的脚本例如中所看到的,DUMP运算符是无价的,它不仅可以查看数据,还可以查看数据架构。您还可以使用DESCRIBE运算符来生成一个关系架构的详细格式〔字段和类型〕。

E*PLAIN运算符更复杂一些,但也很有用。对于*个给定的关系,您可以使用E*PLAIN来查看如何将物理运算符分组为Map和Reduce任务〔也就是说,如何推导出数据〕。表2对PigLatin中的诊断运算符及其描述提供了一个列表。表2.PigLatin诊断运算符运算符描述

DESCRIBE返回关系的架构。

DUMP将关系的内容转储到屏幕。

E*PLAIN显示MapReduce执行方案。

--------------------------------------------------------------------------------

回页首用户定义的函数虽然Pig在本文探讨的范围内是强大且有用的,但是通过用户定义的函数(UDF)可以使它变得更强大。Pig脚本可以使用您为解析输入数据、格式化输出数据甚至运算符等定义的函数。UDF是用Java语言编写的,允许Pig支持自定义处理。UDF是将Pig扩展到您的特定应用程序领域的一种方式。您可以在参考资料中了解有关UDF开发的更多信息。

--------------------------------------------------------------------------------

回页首

Pig用户正如您从这篇短文中可以看到的,Pig是一个强大的工具,可以在Hadoop集群中查询数据。它是如此强大,Yahoo!估计,其Hadoop工作负载中有40%至60%由PigLatin脚本产生。在Yahoo!的100,000个CPU中,大约有50%的CPU仍在运行Hadoop。但Yahoo!并不是利用Pig的惟一组织。您在Twitter中也会发现Pig〔用于处理日志和挖掘微博数据〕;在AOL和MapQuest上也会发现它〔用于分析和批量数据处理〕;而在LinkedIn上,Pig用于发现您可能认识的人。据报道,Ebay使用Pig来实现搜索优化,而adyard的推荐工具系统有大约一半都使用了Pig。PIG安装Pig安装与配置教程

Pig版块到现在都没人写一篇,甚至转载一篇,为了使版面好看点,抽了点时间写篇技术含量≈0的Pig安装配置教程。

Pig是yahoo捐献给apache的一个工程,它是SQL-like语言,是在MapReduce上构建的一种高级查询语言,把一些运算编译进MapReduce模型的Map和Reduce中,并且用户可以定义自己的功能。这是Yahoo开发的又一个克隆Google的工程:Sawzall。

Pig是一个客户端应用程序,就算你要在Hadoop集群上运行Pig,也不需要在集群上装额外的东西。Pig的安装是灰常的简单的:

1、安装JAVA6〔在Windows的话要装Cygwin〕,设置好JAVA_HOME。

%e*portJAVA_HOME=/home/tom/jdk1.6

2、到下载一个稳定的发行版〔目前是,可以在Hadoop-0.20.*上运行〕,解压到你的工作空间:

%tar*zfpig-*.y.z.tar.gz

3、为了方便,可以把Pig的程序目录放到命令行路径里,比方:

%e*portPIG_INSTALL=/home/tom/pig-*.y.z

%e*portPATH=$PATH:$PIG_INSTALL/bin

注销或重启,你就可以用pig-help来查看使用帮助了,安装够简单吧?:〕

Pig有两种模式:一种是Localmode,也就是本地模式,这种模式下Pig运行在一个JVM里,访问的是本地的文件系统,只适合于小规模数据集,一般是用来体验Pig。而且,它并没有用到Hadoop的Localrunner,Pig把查询转换为物理的Plan,然后自己去执行。在终端下输入

%pig-*local

就可以进入Local模式了。还有一种就是Hadoop模式了,这种模式下,Pig才真正的把查询转换为相应的MapReduceJobs,并提交到Hadoop集群去运行,集群可以是真实的分布式也可以是伪分布式。要想Pig能认识Hadoop,你要告诉它Hadoop的版本以及一些关键daemon的信息〔也就是Namenode和Jobtracker的Address和Port〕。比方,下面这个可以允许Pig连接到任何Hadoop0.20.*上:

%e*portPIG_HADOOP_VERSION=20

接下来,你还要指明集群的Namenode和Jobtracker的所在。有两种方法,一种就是把你Hadoop的Conf地址添加到Pig的Classpath上:

%e*portPIG_CLASSPATH=$HADOOP_INSTALL/conf/

还有一种就是在Pig目录的Conf文件夹〔可能需要自己创立〕里创立一个perties文件,然后在里面添加集群的Namenode和Jobtracker的信息:

=hdfs://localhost/

mapred.job.tracker=localhost:8021

搞定后,在终端执行下面的命令:

%pig

你就会看到下面的信息:

2009-03-2921:22:20,489[main]INFO

org.apache.pig.backend.hadoop.e*ecutionengine.

HE*ecutionEngine–Connectingtohadoopfilesystemat:hdfs://localhost/

2009-03-2921:22:20,760[main]INFO

org.apache.pig.backend.hadoop.e*ecutionengine.

HE*ecutionEngine–Connectingtomap-reducejobtrackerat:localhost:8021

grunt>

如你所见,Pig报告已经连上了Hadoop的Namenode和Jobtracker,是不是也灰常的简单?PIG实战Pig实战1.pig简介2.安装pig3.实战pig4.深入pig5.参考资料及代码下载<1>.Pig简介pig是hadoop工程的一个拓展工程,用以简化hadoop编程〔简化的程度超乎想象啊〕,并且提供一个更高层次抽象的数据处理能力,同时能够保持hadoop的简单和可靠性。<2>.安装pig2.1下载pig:[点击下载]pig安装包2.2解压下载完成的pig安装包:2.3设置环境变量*uqiangubuntu:~$vim.bashrce*portPATH=~/hadoop/src/pig/pig-0.8.1/bin/:$PATH这里需要说明的是pig是能够运行在两种模式下:local模式和mapreduce模式,变量HADOOP_CONF_DIR主要是为了在mapreduce模式下使用。为了使新设置的环境变量生效,使用如下命令:*uqiangubuntu:~$source.bash_profile测试一下pig的安装是否正确:*uqiangubuntu:~$pig-*local2011-06-0517:48:49,480[main]INFOorg.apache.pig.Main-Loggingerrormessagesto:/home/*uqiang/pig_71.log2011-06-0517:48:49,926[main]INFOorg.apache.pig.backend.hadoop.e*ecutionengine.HE*ecutionEngine-Connectingtohadoopfilesystemat:file:///grunt>此时说明pig已经正确安装。<3>.Pig实战在pig下载的安装包,解压完成了之后,有一个tutorial目录,我们使用里面的数据来开场pig学习。如果tutorial目录下没有存在文件的话,则需要使用ant来编译出这个文件:*uqiangubuntu:~/hadoop/src/pig/pig-0.8.1$ant这时ant将会下载依赖的jar的文件,同时将编译出对应版本的pigjar文件。然后进入tutorial目录,执行ant命令:*uqiangubuntu:~/hadoop/src/pig/pig-0.8.1$cdtutorial/*uqiangubuntu:~/hadoop/src/pig/pig-0.8.1/tutorial$ant这时将生成文件,解压该文件形成pigtmp的文件夹。该文件夹构造:.|--e*cite-small.log|--pig.jar|--script1-hadoop.pig|--script1-local.pig|--script2-hadoop.pig|--script2-local.pig`--tutorial.jar1directory,9files我们下面将主要分析e*cite-small.log文件,该文件的数据构造如下:UserIDTimeStampSearchQuery我们首先将e*cite-small.log加载到一个变量〔也称之为alias〕中,我们将使用该变量来表示这个数据集:grunt>log=load'e*cite-small.log'as(user,time,query);注意的是这时pig并没有运行该命令,仅仅是解析了该命令,只有到使用dump命令或者是store命令时pig才会真正执行该命令。dump命令将打印出这个变量的内容,store命令将变量所代表的内容保存到一个文件中。这时如果想要查看该log的构造:grunt>describelog;log:{user:bytearray,time:bytearray,query:bytearray}这是如果我们想要查看该log文件的前4行的话:grunt>lmt=limitlog4;grunt>dumplmt;这时将打印出log文件的前四行数据。<4>.深入pig4.1Utilityandfilecommands4.2Dataread/writeoperators4.3Diagnosticoperators诊断操作4.4Datatypeandschemespig中有6个根本数据类型和3个复合数据类型,根本数据类型如下:复合数据类型:pig中数据模型中能够允许数据类型的嵌套,类似于*ml/json格式。4.5E*pressionandfunctionspig能够支持常见运算符。同时在pig中提供了一些内建函数。这里我们没有给出例如,将在下面给出例如。4.6Retionaloperators首先编写两个数据文件A:0,1,21,3,4数据文件B:0,5,21,7,8运行pig:*uqiangubuntu:~/hadoop/src/pig/pig-0.8.1/tutorial/pigtmp$pig-*local2011-06-0518:46:54,324[main]INFOorg.apache.pig.backend.hadoop.e*ecutionengine.HE*ecutionEngine-Connectingtohadoopfilesystemat:file:///grunt>加载数据A:grunt>a=load'A'usingPigStorage(',')as(a1:int,a2:int,a3:int);加载数据B:grunt>b=load'B'usingPigStorage(',')as(b1:int,b2:int,b3:int);求a,b的并集:grunt>c=uniona,b;grunt>dumpc;(0,5,2)(1,7,8)(0,1,2)(1,3,4)将c分割为d和e,其中d的第一列数据值为0,e的第一列的数据为1〔$0表示数据集的第一列〕:grunt>splitcintodif$0==0,eif$0==1;查看d:grunt>dumpd;(0,1,2)(0,5,2)查看e:(1,3,4)(1,7,8)选择c中的一局部数据:grunt>f=filtercby$1>3;查看数据f:grunt>dumpf;(0,5,2)(1,7,8)对数据进展分组:grunt>g=groupcby$2;查看g:grunt>dumpg;(2,{(0,1,2),(0,5,2)})(4,{(1,3,4)})(8,{(1,7,8)})当然也能够将所有的元素集合到一起:grunt>h=groupcall;grunt>dumph;(all,{(0,1,2),(1,3,4),(0,5,2),(1,7,8)})查看h中元素个数:grunt>i=foreachhgenerateCOUNT($1);查看元素个数:grunt>dumpi;这里可能出现Couldnotresolvecounterusingimported:[,org.apache.pig.builtin.,org.apache.pig.impl.builtin.]的情况,这是需要使用register命令来注册pig对应的jar版本。接下俩试一下jon操作:grunt>j=joinaby$2,bby$2;该操作类似于sql中的连表查询,这是的条件是$2==$2。取出c的第二列$1和$1*$2,将这两列保存在k中:grunt>k=foreachcgenerate$1,$1*$2;查看k的内容:grunt>dumpk;(5,10)(7,56)(1,2)(3,12)4.7WorkingwithUDF(userdefinedfunction)pig能够支持两种类型的UDFs:eval和load/store,其中load/store的自定义函数主要是用来加载和保存特定的数据格式;eval自定义函数主要用来进展常规的数据转换。1.eval如果想要实现自定义的eval类型的函数,则根本的做法是首先编写一个类继承自EvalFunc<T>这个抽象类,同时需要重写这个类的一方法:abstractpublicTe*ec(Tupleinput)throwsIOE*ception;该方法传入的类型是Tuple类型。如果调用udf时使用的是:udf(ARG1,ARG2);则调用input.get(0)将得到ARG1,同理input.get(1)得到的是ARG2,input.getSize()得到传递的参数的数量,这里就是2.下面我们就开场编写udfUPPER.java,将UPPER.java文件保存到myudfs目录下:packagemyudfs;

importjava.io.IOE*ception;

importorg.apache.pig.EvalFunc;

importorg.apache.pig.data.Tuple;

importorg.apache.pig.impl.util.WrappedIOE*ception;

publicclassUPPERe*tendsEvalFunc<String>

{

publicStringe*ec(Tupleinput)throwsIOE*ception{

if(input==null||input.size()==0)

returnnull;

try{

Stringstr=(String)input.get(0);

returnstr.toUpperCase();

}catch(E*ceptione){

throwWrappedIOE*ception.wrap("Caughte*ceptionprocessinginputrow",e);

}

}}编译该文件,同时生成该jar文件:*uqiangubuntu:~/hadoop/src/pig/pig-0.8.1/myudfs$javac-cp../pig.jarUPPER.java*uqiangubuntu:~/hadoop/src/pig/pig-0.8.1/myudfs$cd..*uqiangubuntu:~/hadoop/src/pig/pig-0.8.1$jar-cfmyudfs.jarmyudfs准备student_data文件:student1,1,1

studetn2,2,2

student3,3,3

student4,4,4在pig中测试该udf:*uqiangubuntu:~/hadoop/src/pig/pig-0.8.1$pig-*local注册该udf:grunt>registermyudfs.jar加载数据:grunt>A=load'student_data'usingPigStorage(',')as(name:chararray,age:int,gpa:double);grunt>B=FOREACHAGENERATEmyudfs.UPPER(name);grunt>dumpB;这时将输出:(STUDENT1)

(STUDETN2)

(STUDENT3)

(STUDENT4)ApachePig的一些根底概念及用法总结〔1〕Apachepig是用来处理大规模数据的高级查询语言,配合Hadoop使用,可以在处理海量数据时到达事半功倍的效果,比使用Java,C++等语言编写大规模数据处理程序的难度要小N倍,实现同样的效果的代码量也小N倍。Twitter就大量使用pig来处理海量数据——有兴趣的,可以看Twitter工程师写的这个PPT。但是,刚接触pig时,可能会觉得里面的*些概念以及程序实现方法与想像中的很不一样,甚至有些莫名,所以,你需要仔细地研究一下根底概念,这样在写pig程序的时候,才不会觉得非常别扭。本文基于以下环境:先给出两个链接:pig参考手册1,pig参考手册2。本文的局部内容来自这两个手册,但涉及到翻译的局部,也是我自己翻译的,因此可能理解与英文有偏差,如果你觉得有疑义,可参考英文内容。【配置Pig语法高亮】在正式开场学习Pig之前,你首先要明白,配置好编辑器的Pig语法高亮是很有用的,它可以极大地提高你的工作效率。如果你在Windows下编写Pig代码,好似还真没有什么轻量级的编辑器插件〔例如Notepad++的插件之类的〕可以实现对.pig文件的语法高亮显示,我建议你使用Notepad++,在"UserDefineLanguage〞中自定义Pig语法高亮方案〔我这样做之后感觉效果很好〕;如果你觉得麻烦,则你可以直接用Notepad++以SQL的语法高亮来查看Pig代码,这样的话可以高亮Pig中的一局部关键字。在Linu*下,选择就很多了,大分部人使用的是vi,vim,但我是个Emacs控,所以我就先说说如何配置Emacs的Pig语法高亮。此插件是一个很好的选择:s://github./cloudera/piglatin-mode则,怎么使用这个插件呢?下载piglatin.el文件,将它放置在任何地方——当然,为了方便,最好是放在你登录用户的根目录下〔也就是与.emacs配置文件在同一目录下〕,然后将其重命名为".piglatin.el〞注意前面是有一个点的,也就是说将这个文件设置成隐藏文件,否则可能会误删了。然后,在.emacs文件中的最后,添加上如下一行:(load-file"/home/abc/.piglatin.el")这里假设了你的.piglatin.el文件放置的位置是在/home/abc/目录下,也就是说emacs会加载这个文件,实现语法高亮显示。现在,你再翻开一个.pig文件试试看?非常令人赏心悦目的高亮效果就出来了。效果如下列图所示:其实Emacs也有Windows版的,如果你习惯在Windows下工作,完全可以在Windows下按上面的方法配置一下Pig语法高亮〔但是Windows版的Emacs还需要一些额外的配置工作,例如修改注册表等,所以会比在Linu*下使用要麻烦一些,具体请看这篇文章〕。文章来源:.codelast./下面开场学习Pig。〔1〕关系〔relation〕、包〔bag〕、元组〔tuple〕、字段〔field〕、数据〔data〕的关系一个关系〔relation〕是一个包〔bag〕,更具体地说,是一个外部的包〔outerbag〕。一个包〔bag〕是一个元组〔tuple〕的集合。在pig中表示数据时,用大括号{}括起来的东西表示一个包——无论是在教程中的实例演示,还是在pig交互模式下的输出,都遵循这样的约定,请牢记这一点,因为不理解的话就会对数据构造的掌握产生偏差。一个元组〔tuple〕是假设干字段〔field〕的一个有序集〔orderedset〕。在pig中表示数据时,用小括号()括起来的东西表示一个元组。一个字段是一块数据〔data〕。"元组〞这个词很抽象,你可以把它想像成关系型数据库表中的一行,它含有一个或多个字段,其中,每一个字段可以是任何数据类型,并且可以有或者没有数据。

"关系〞可以比喻成关系型数据库的一张表,而上面说了,"元组〞可以比喻成数据表中的一行,则这里有人要问了,在关系型数据库中,同一张表中的每一行都有固定的字段数,pig中的"关系〞与"元组〞之间,是否也是这样的情况呢?不是的。"关系〞并不要求每一个"元组〞都含有一样数量的字段,并且也不会要求各"元组〞中在一样位置处的字段具有一样的数据类型〔太随意了,是吧?〕文章来源:.codelast./〔2〕一个计算多维度组合下的平均值的实际例子为了帮助大家理解pig的一个根本的数据处理流程,我造了一些简单的数据来举个例子——

假设有数据文件:a.t*t〔各数值之间是以tab分隔的〕:1234567[rootlocalhostpig]$cata.t*t

a1234.29.8a3053.52.1b799--a7992.66.2a1257.75.9a1231.40.2问题如下:怎样求出在第2、3、4列的所有组合的情况下,最后两列的平均值分别是多少?例如,第2、3、4列有一个组合为〔1,2,3〕,即第一行和最后一行数据。对这个维度组合来说,最后两列的平均值分别为:〔4.2+1.4〕/2=2.8

〔9.8+0.2〕/2=5.0

而对于第2、3、4列的其他所有维度组合,都分别只有一行数据,因此最后两列的平均值其实就是它们自身。特别地,组合〔7,9,9〕有两行记录:第三、四行,但是第三行数据的最后两列没有值,因此它不应该被用于平均值的计算,也就是说,在计算平均值时,第三行是无效数据。所以〔7,9,9〕组合的最后两列的平均值为2.6和6.2。我们现在用pig来算一下,并且输出最终的结果。先进入本地调试模式〔pig-*local〕,再依次输入如下pig代码:1234A=LOAD'a.t*t'AS(col1:chararray,col2:int,col3:int,col4:int,col5:double,col6:double);B=GROUPABY(col2,col3,col4);C=FOREACHBGENERATEgroup,AVG(A.col5),AVG(A.col6);DUMPC;pig输出结果如下:1234((1,2,3),2.8,5.0)((1,2,5),7.7,5.9)((3,0,5),3.5,2.1)((7,9,9),2.6,6.2)这个结果对吗?手工算一下就知道是对的。文章来源:.codelast./下面,我们依次来看看每一句pig代码分别得到了什么样的数据。①加载a.t*t文件,并指定每一列的数据类型分别为chararray〔字符串〕,int,int,int,double,double。同时,我们还给予了每一列别名,分别为col1,col2,……,col6。这个别名在后面的数据处理中会用到——如果你不指定别名,则在后面的处理中,就只能使用索引〔$0,$1,……〕来标识相应的列了,这样可读性会变差,因此,在列固定的情况下,还是指定别名的好。将数据加载之后,保存到变量A中,A的数据构造如下:1A:{col1:chararray,col2:int,col3:int,col4:int,col5:double,col6:double}可见,A是用大括号括起来的东西。根据本文前面的说法,A是一个包〔bag〕。这个时候,A与你想像中的样子应该是一致的,也就是与前面打印出来的a.t*t文件的内容是一样的,还是一行一行的类似于"二维表〞的数据。文章来源:.codelast./②按照A的第2、3、4列,对A进展分组。pig会找出所有第2、3、4列的组合,并按照升序进展排列,然后将它们与对应的包A整合起来,得到如下的数据构造:1B:{group:(col2:int,col3:int,col4:int),A:{col1:chararray,col2:int,col3:int,col4:int,col5:double,col6:double}}可见,A的第2、3、4列的组合被pig赋予了一个别名:group,这很形象。同时我们也观察到,B的每一行其实就是由一个group和假设干个A组成的——注意,是假设干个A。这里之所以只显示了一个A,是因为这里表示的是数据构造,而不表示具体数据有多少组。实际的数据为:1234((1,2,3),{(a,1,2,3,4.2,9.8),(a,1,2,3,1.4,0.2)})((1,2,5),{(a,1,2,5,7.7,5.9)})((3,0,5),{(a,3,0,5,3.5,2.1)})((7,9,9),{(b,7,9,9,,),(a,7,9,9,2.6,6.2)})可见,与前面所说的一样,组合〔1,2,3〕对应了两行数据,组合〔7,9,9〕也对应了两行数据。这个时候,B的构造就不则明朗了,可能与你想像中有一点不一样了。文章来源:.codelast./③计算每一种组合下的最后两列的平均值。根据上面得到的B的数据,你可以把B想像成一行一行的数据〔只不过这些行不是对称的〕,FOREACH的作用是对B的每一行数据进展遍历,然后进展计算。

GENERATE可以理解为要生成什么样的数据,这里的group就是上一步操作中B的第一项数据〔即pig为A的第2、3、4列的组合赋予的别名〕,所以它告诉了我们:在数据集C的每一行里,第一项就是B中的group——类似于〔1,2,5〕这样的东西〕。而AVG(A.col5)这样的计算,则是调用了pig的一个求平均值的函数AVG,用于对A的名为col5的列求平均值。前文说了,在加载数据到A的时候,我们已经给每一列起了个别名,col5就是倒数第二列。到这里,可能有人要迷糊了:难道AVG(A.col5)不是表示对A的col5这一列求平均值吗?也就是说,在遍历B〔FOREACHB〕的每一行时候,计算结果都是一样的啊!事实上并不是这样。我们遍历的是B,我们需要注意到,B的数据构造中,每一行数据里,一个group对应的是假设干个A,因此,这里的A.col5,指的是B的每一行中的A,而不是包含全部数据的那个A。拿B的第一行来举例:

((1,2,3),{(a,1,2,3,4.2,9.8),(a,1,2,3,1.4,0.2)})

遍历到B的这一行时,要计算AVG(A.col5),pig会找到

(a,1,2,3,4.2,9.8)中的4.2,以及(a,1,2,3,1.4,0.2)中的1.4,加起来除以2,就得到了平均值。同理,我们也知道了AVG(A.col6)是怎么算出来的。但还有一点要注意的:对(7,9,9)这个组,它对应的数据(b,7,9,9,,)里最后两列是无值的,这是因为我们的数据文件对应位置上不是有效数字,而是两个"-〞,pig在加载数据的时候自动将它置为空了,并且计算平均值的时候,也不会把这一组数据考虑在内〔相当于忽略这组数据的存在〕。到了这里,我们不难理解,为什么C的数据构造是这样的了:1C:{group:(col2:int,col3:int,col4:int),double,double}文章来源:.codelast./④DUMPC就是将C中的数据输出到控制台。如果要输出到文件,需要使用:1STORECINTO'output';这样pig就会在当前目录下新建一个"output〞目录〔该目录必须事先不存在〕,并把结果文件放到该目录下。请想像一下,如果要实现一样的功能,用Java或C++写一个Map-Reduce应用程序需要多少时间?可能仅仅是写一个build.*ml或者Makefile,所需的时间就是写这段pig代码的几十倍了!正因为pig有如此优势,它才得到了广泛应用。文章来源:.codelast./〔3〕怎样统计数据行数在SQL语句中,要统计表中数据的行数,很简单:1SELECTCOUNT(*)FROMtable_nameWHEREcondition在pig中,也有一个COUNT函数,在pig手册中,对COUNT函数有这样的说明:Computesthenumberofelementsinabag.假设要计算数据文件a.t*t的行数:1234567[rootlocalhostpig]$cata.t*t

a1234.29.8a3053.52.1b799--a7992.66.2a1257.75.9a1231.40.2你是否可以这样做呢:123A=LOAD'a.t*t'AS(col1:chararray,col2:int,col3:int,col4:int,col5:double,col6:double);B=COUNT(*);DUMPB;答案是:绝对不行。pig会报错。pig手册中写得很明白:Note:Youcannotusethetupledesignator(*)withCOUNT;thatis,COUNT(*)willnotwork.则,这样对*一列计数行不行呢:1B=COUNT(A.col2);答案是:仍然不行。pig会报错。这就与我们想像中的"正确做法〞有点不一样了:我为什么不能直接统计一个字段的数目有多少呢?刚接触pig的时候,一定非常疑惑这样明显"不应该出错〞的写法为什么行不通。要统计A中含col2字段的数据有多少行,正确的做法是:1234A=LOAD'a.t*t'AS(col1:chararray,col2:int,col3:int,col4:int,col5:double,col6:double

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论