Pig简述
- Pig是一个用来处理大规模数据集的平台,由Yahoo!贡献给Apache
- Pig可以简化MapReduce仸务的开发
- Pig可以看做hadoop的客户端软件,可以连接到hadoop集群迕行数据分析工作
- Pig方便不熟悉java的用户,使用一种较为简便的类似二SQL的面向数据流的语言pig Latin迕行数据处理
- Pig Latin可以迕行排序、过滤、求和、分组、关联等常用操作,迓可以自定义凼数,返是一种面向数据分析处理的轻量级脚本语言
- Pig可以看做是Pig Latin到MapReduce的映射器
- Pig可以自动对集群迕行分配和回收,幵丏自劢地对MapReduce程序迕行优化
Pig的安装和工作模式
安装步骤
- 下载并解压pig安装包( http://pig.apache.org/)
- 设置环境变量
PIG_HOME=/root/training/pig-0.17.0
export PIG_HOME
PATH=$PIG_HOME/bin:$PATH
export PATH
工作模式
本地模式:操作的是Linux的文件
pig -x local
集群模式:链接到HDFS上
设置一个环境变量: PIG_CLASSPATH ----> Hadoop的配置文件所在的目录
PIG_CLASSPATH=$HADOOP_HOME/etc/hadoop
export PIG_CLASSPATH
Pig的常用命令:操作HDFS
ls、cd、cat、mkdir、pwd
copyFromLocal(上传)、copyToLocal(下载)
sh: 调用操作系统的命令
register、define -----> 部署pig的自定义函数的jar包
Pig的数据模型
Bag ---> tuple--------->field(可以嵌套Bag)
Pig不要求同一个bag里面的各个tuple有相同数量或相同类型的field
Pig的内置函数
计算函数
avg 计算包中项的平均值
concat 把两个字节数组或者字符数组连接成一个
count 计算包中非空值的个数
count_star 计算包中项的个数,包括空值
diff 计算两个包的差
max 计算包中项的最大值
min 计算包中项的最小值
size 计算一个类型的大小,数值型的大小为1;
对于字符数组,返回字符的个数;
对于字节数组,返回字节的个数;
对于元组,包,映射,返回其中项的个数。
sum 计算一个包中项的值的总和
TOKENIZE 对一个字符数组进行标记解析,并把结果词放入一个包
过滤函数
isempty 判断一个包或映射是否为空
加载存储函数
PigStorage 用字段分隔文本格式加载或存储关系,这是默认的存储函数
BinStorage 从二进制文件加载一个关系或者把关系存储到二进制文件
BinaryStorage 从二进制文件加载只是包含一个类型为bytearray的字段的元组到关系,或以这种格式存储一个关系
TextLoader 从纯文本格式加载一个关系
PigDump 用元组的tostring()形式存储关系
使用PigLatin语句分析数据
需要启动Yarn的HistoryServer:记录所有执行过的任务
mr-jobhistory-daemon.sh start historyserver
URL: http://ip:19888/jobhistory
常见的PigLatin语句(注意:PigLatin语句跟Spark中算子/方法非常像)
(*)load 加载数据到表(bag)
(*)foreach 相当于循环,对bag中每一个行tuple进行处理
(*)filter 过滤、相当于where
(*)group by 分组
(*)order by 排序
(*)join 链接
(*)generate 提取列
(*)union、intersect 集合运算
(*)输出:dump 屏幕
store 保存到文件
注意:PigLatin有些会触发计算,有些不会
类似Spark RDD 算子(方法):Transformation方法(算子) -----> 不会触发计算
Action方法(算子) ------> 会触发Spark的计算
使用PigLatin语句
创建员工表
表名 = load 'hdfs路径’ using PigStorage('制定分割') as (字段1:类型,字段2:类型,....);
emp = load '/scott/emp.csv' as(empno,ename,job,mgr,hiredate,sal,comm,deptno);
默认的列的类型:bytearray
默认的分隔符:制表符
查看表结构
describe emp;
查询员工信息:员工号 姓名 薪水
emp3 = foreach emp generate empno,ename,sal;
dump emp3;
查询员工信息,按照月薪排序
emp4 = order emp by sal;
dump emp4;
分组:求每个部门的最高工资: 部门号 部门的最高工资
emp51 = group emp by deptno;
查看表结构:
emp51: {group: int,
emp: {(empno: int,ename: chararray,job: chararray,mgr: int,hiredate: chararray,sal: int,comm: int,deptno: int)}}
emp52 = foreach emp51 generate group,MAX(emp.sal)
查询10号部门的员工
emp6 = filter emp by deptno==10; 注意:两个等号
多表查询:部门名称、员工姓名
emp71 = join dept by deptno,emp by deptno;
emp72 = foreach emp71 generate dept::dname,emp::ename;
集合运算:
emp10 = filter emp by deptno==10;
emp20 = filter emp by deptno==20;
emp1020 = union emp10,emp20;
执行WordCount
① 加载数据
mydata = load '/input/data.txt' as (line:chararray);
② 将字符串分割成单词
words = foreach mydata generate flatten(TOKENIZE(line)) as word;
③ 对单词进行分组
grpd = group words by word;
④ 统计每组中单词数量
cntd = foreach grpd generate group,COUNT(words);
⑤ 打印结果
dump cntd;
Pig的自定义函数:3种
//Pig的自定义函数:3种 ---> 打成jar包
/**
* 自定义过滤函数
* @author Administrator
*/
public class SelectSal extends FilterFunc{
@Override
public Boolean exec(Tuple tuple) throws IOException {
Object object = tuple.get(0);//tuple 行
int sal = Integer.parseInt(String.valueOf(object));
if (sal<2000) {
return false;
}else {
return true;
}
}
}
/**
* 自定义运算函数
* 继承类 EvalFunc<T> T 制定返回类型
*/
public class SelectGrade extends EvalFunc<String>{
@Override
public String exec(Tuple tuple) throws IOException {
Object object = tuple.get(0);//tuple 行
int sal = Integer.parseInt(String.valueOf(object));
if (sal<1500) {
return "Grade A";
}else if (sal<=3000 && sal >=1500) {
return "Grade B";
}else {
return "Grade C";
}
}
}
/**
* 自定义加载函数
*/
public class MyLoadFunc extends LoadFunc{
private RecordReader reader;
@Override
public InputFormat getInputFormat() throws IOException {
// TODO Auto-generated method stub
return new TextInputFormat();
}
@Override
public Tuple getNext() throws IOException {
Tuple tuple = null;
try {
if (!reader.nextKeyValue()) {
return null; //读完了
}
tuple = TupleFactory.getInstance().newTuple();
Text text = (Text) reader.getCurrentValue(); //读取的每行
String value = text.toString();
//生成bag
DataBag bag = BagFactory.getInstance().newDefaultBag();
String[] values = value.split(" ");
for (String word : values) {
Tuple tuple2 = TupleFactory.getInstance().newTuple();
tuple2.append(word);//每个单词是一个tuple
bag.add(tuple2);//一行就是 一个bag
}
tuple.append(bag);
} catch (InterruptedException e) {
e.printStackTrace();
}
return tuple;
}
@Override
public void prepareToRead(RecordReader reader, PigSplit arg1) throws IOException {
// TODO Auto-generated method stub
this.reader = reader;
}
@Override
public void setLocation(String location, Job job) throws IOException {
// TODO Auto-generated method stub
FileInputFormat.setInputPaths(job, new Path(location));
}
}
register /root/temp/pigfunc.jar
define myloadfunc pig.MyLoadFunction;
mydemo = load '/input/data.txt' using pig.MyLoadFunction();