5.1 基础知识
5.1.1 大小写敏感
Pig Latin无法明确说是否大小写敏感。Pig Latin 中的关键字是非大小写敏感,例如LOAD和load是等价的。但是关系名称和字段名称是大小写敏感的。因此A = load ‘foo’;和 a = load ‘foo’;是不等价的。用户自定义函数UDF的名称也是大小写敏感的,因此COUNT和count所指的并非是同一个UDF;
5.1.2 注释
Pig Latin具有两种注释方式:SQL样式的单行注释(–)和java样式的多行注释(/* */).
5.2 输入和输出
5.2.1 加载
任何一种数据流的第一步都是要指定输入。在Pig Latin中是通过LOAD语句来完成的。默认情况下,load使用默认加载函数PigS toStorage加载存放在HDFS中并且以制表建进行分割的文件。例如,语句divs = load ‘NYSE_dividends’;用户也可以指定一个完整的URL路径,例如,hdfs://nn.acme.com/data/NYSE_dividends,这可以从NameNode为nn.acme.com的HDFS实例中读取文件。
实际上,用户的大部分数据并非是使用制表键做分割符的文本文件,也有可能需要从其它非HDFS的存储系统中加载数据。Pig允许用户在加载数据时通过using句式指定其它加载函数。例如,想从HBase中加载数据:
divs = load ‘NYSE_dividends’ using HBasestorage();
如果没有指定加载函数,那么会使用内置的加载函数PigStorage。用户同样可以通过using句式为使用的加载函数指定参数。例如,如果想读取以逗号分割的文本文件数据,那么PigStorage会接收一个指定分割符的参数:
divs = load ‘NYSE_dividends’ using PigStorage(‘,’);
load语句也可以有as句式,这个句式可以为用户加载的数据指定模式。模式相当于列名。
当从HDFS访问指定‘文件’的时候,用户也可以指定文件夹。在这种情况下,Pig会遍历用户指定的文件夹下的所有文件并将他们作为load语句的输入。
PigStorage和TextLoader,这两个内置的可操作HDFS文件的Pig加载函数,是支持模式匹配的。通过模式匹配,用户可以读取不在同一个目录下的多个文件或者读取一个文件下的部分文件。
正则匹配语法
正则字符 |
描述 |
? | 匹配任何单个字符 |
* | 匹配零个或多个字符 |
[abc] | 匹配字符集合{a,b,c}所包含的任何一个字符 |
[a-z] | 匹配指定范围内的任意字符 |
[^abc] | 匹配未包含的任意字符,其中^符号匹配输入字符串的开始位置 |
[^a-z] | 匹配任何不在指定范围内的任意字符 |
\c | 移除(转义)字符c所表达的特殊含义 |
{ab,cd} | 配置字符串集合{ab,cd}中的任一字符串 |
5.2.2 存储
当用户处理完数据之后,需哟啊把结果写到某个地方。Pig提供了store语句来进行写数据。在许多方面,它是load语法的镜像。默认情况下,Pig使用PigStorage将结果数据以制表键作为分割符存储到HDFS中:store processed into ‘/data’.
如果用户没有显示的指定存储函数,那么将会默认使用PigStorage。用户可以使用using语句指定不同的存储函数:store processed into ‘processed’ using HBaseStorage();
用户也可以传参数给其使用的存储函数。例如,如果想将数据存储为以逗号分隔的文本数据,PigStorage会接收一个指定分隔符的参数:store processed into ‘processed’ using PigStorage(‘,’);
当写到文件系统中后,processed是一个包含多个部分文件的文件夹,而不是一个文件夹。但是至于会生成多少个部分文件,这要取决于执行store前的最后一个任务的并行数,该值由为这个任务所设置的并行级别所决定。
5.2.3 输出
将结果数据输出到屏幕,对于调试阶段和原型研究阶段是特别有用的。dump语句可以将用户的脚本输出打印到屏幕上。dump processed。
map用[ ](方括号)分隔,tuple使用()(圆括号),bag使用{}(花括号)
5.3 关系操作
5.3.1 foreach
foreach语句接受的是一组表达式,然后在数据管道中将他们应用到每条记录中,因此命名为foreach。通过这些表达式,它会产生出新的数据并传送给下一个操作符。
prices = load ‘NYSE_daily’ as(exchange,symbol,date,open,high,low,close,volumn,adj_close);
gain = foreach prices generate close – open;
gain2 = foreach prices generate $6 – $3;
除了使用别名和位置,用户可以使用*(星号)代表所有字段,也可以用 ..(两个点)来指定字段区间:
prices = load ‘NYSE_dairy’ as (exchange,symbol,date,open,high,low,close,volumn,adj_close);
beginning = foreach prices generate date .. low;
end = foreach prices generate volumn .. ;
null 对于所有的算术操作符都是抵消的。也就是说,x + null = null,这里不管x是什么类型的值都是成立的。
Pig同样提供了一个三元条件操作符,经常被称为bincond。它以一个布尔表达式开始,后面跟一个?(问号),然后跟着是如果前面布尔表达式为真的时候返回的值,后面再跟着:(冒号),最后跟着如果前面布尔表达式为假时返回的值。如果前面的布尔表达式返回为null,那么整个表达式返回为null。表达式中的?后的两个值应该是相同的数据类型:
2 == 2 ?1 :4 — 返回 1
2 == 3 ?1 :4 — 返回 4
null == 2 ?1 :4 — 返回null
2 == 2 ?1:‘fred’ –类型错误;冒号两边的值应该是相同的数据类型
为了从复杂的数据类型中提取出值, 需要使用投射运算符。对于map是使用#(也就是散列表),然后后面跟着一个字符串类型的键的名称。需要注意的是一个键对应的值可以是任何数据类型的。如果用户使用的键在map中不存在,那么结果是null:
bball = load ‘baseball’ as (name:chararray,team:chararray,position:bag{t:(p:chararray)},bat:map[]);
avg = foreach bball generate bat#’batting_average’;
tuple的映射是用.(点操作符)符号的。最外层的数据记录,可以通过字段名指定一个字段,对tuple通过位置进行引用,如果该位置不存在,则会返回null。
A = load ‘input’ as (t:tuple(x:int,y:int));
B = foreach A generate t.x,t.y;
对于bag的映射并不像map和tuple映射那么简单了。bag并不会保证它内部存放的tuple是以有序的方式存放的,因此对一个bag中的tuple进行映射是没有意义的。反之,当用户需要映射一个bag中的字段的时候,可以通过创建一个包含用户需要的字段的bag:
A = load ‘input’ as (b:bag{t:(x:int,y:int)});
B = foreach A generate b.x;
这会创建一个新的bag,其中只有字段x在里面。用户可以通过使用圆括号中标明逗号分隔的字段名称的方式映射多个字段:
A = load ‘input’ as (b:bag{t:(x:int,y:int)});
B = foreach A generate b.(x,y);
还有一点区别是b.x是bag而不是一个可以进行计算的数量值。
5.3.2 Fileter
5.3.3 Group
5.3.4 Order by
5.3.5 Distinct
5.3.6 Join
5.3.7 Limit
5.3.8 Sample
5.3.9 Parallel
5.4 用户自定义函数UDF
5.4.1 注册UDF
5.4.2 define命令和UDF
5.4.3 调用静态Java函数