使用PigLatin语句分析数据
(*) load: 加载数据到表中(bag)
(*) foreach:对表中的每一条数据tuple进行处理
(*) filter: 相当于where
(*) group by
(*) join : 连接(多表查询)
(*) generate: 提取列
(*) union/intersect:集合运算
(*) 输出:dump 直接打印在屏幕
store 输出到HDFS
数据: 7654,MARTIN,SALESMAN,7698,1981/9/28,1250,1400,30
1、将emp.csv文件加载成一个表(bag)
emp = load '/scott/emp.csv';
查看结构: describe emp
Schema for emp unknown.
2、将emp.csv文件加载成一个表(bag),并且指定tuple个schema
emp1 = load '/scott/emp.csv' as(empno,ename,job,mgr,hiredate,sal,comm,deptno);
默认的数据类型:bytearray
3、将emp.csv文件加载成一个表(bag),并且指定tuple个schema和数据类型
emp2 = load '/scott/emp.csv' as(empno:int,ename:chararray,job:chararray,mgr:int,hiredate:chararray,sal:int,comm:int,deptno:int);
指定分隔符: 使用Pig内置函数 (最终正确的语法)
emp2 = load '/scott/emp.csv' using PigStorage(',') as(empno:int,ename:chararray,job:chararray,mgr:int,hiredate:chararray,sal:int,comm:int,deptno:int);
创建一个部门表: dept
dept = load '/scott/dept.csv' using PigStorage(',') as(deptno:int,dname:chararray,loc:chararray);
4、查询员工信息:员工号 姓名 薪水
SQL: select empno,ename,sal from emp2;
PL: emp4 = foreach emp2 generate empno,ename,sal;
5、查询员工信息,按照月薪排序
MYSQL: select * from emp2 order by sal;
PL: emp5 = order emp2 by sal; (piglatin 语句 )无需去写MapReduce程序
6、分组:查询每个部门工资的最大值
SQL: select deptno,max(sal) from emp2 group by deptno;
PL: (1) 分组数据
emp61 = group emp2 by deptno;
结构:
emp61: {group: int,emp2: {(empno: int,ename: chararray,job: chararray,mgr: int,hiredate: chararray,sal: int,comm: int,deptno: int)}}
数据:
(10,{(7934,MILLER,CLERK,7782,1982/1/23,1300,,10),
(7839,KING,PRESIDENT,,1981/11/17,5000,,10),
(7782,CLARK,MANAGER,7839,1981/6/9,2450,,10)})
(20,{(7876,ADAMS,CLERK,7788,1987/5/23,1100,,20),
(7788,SCOTT,ANALYST,7566,1987/4/19,3000,,20),
(7369,SMITH,CLERK,7902,1980/12/17,800,,20),
(7566,JONES,MANAGER,7839,1981/4/2,2975,,20),
(7902,FORD,ANALYST,7566,1981/12/3,3000,,20)})
(30,{(7844,TURNER,SALESMAN,7698,1981/9/8,1500,0,30),
(7499,ALLEN,SALESMAN,7698,1981/2/20,1600,300,30),
(7698,BLAKE,MANAGER,7839,1981/5/1,2850,,30),
(7654,MARTIN,SALESMAN,7698,1981/9/28,1250,1400,30),
(7521,WARD,SALESMAN,7698,1981/2/22,1250,500,30),
(7900,JAMES,CLERK,7698,1981/12/3,950,,30)})
(2)查询每个部门工资的最大值 (提取generate)
emp62 = foreach emp61 generate group,MAX(emp2.sal);
7、查询10号部门的员工
SQL: select * from emp2 where deptno=10;
PL: emp7 = filter emp2 by deptno==10; 注意:一定是两个等号
8、多表查询:查询员工信息: 员工姓名 部门名称
SQL: select e.ename,d.dname from emp2 e,dept d where e.deptno=d.deptno;
PL: emp81 = join dept by deptno,emp2 by deptno;
emp82 = foreach emp81 generate dept::dname,emp2::ename;
提取部门表中的部门名称 语法类型 两个冒号
dump emp82; //执行查看
9、集合运算:并集 交集 差集
查询10和20号部门的员工信息
SQL: select * from emp2 where deptno=10
union
select * from emp2 where deptno=20;
问题:在SQL中,是否任意的集合都可以进行集合运算?(做集合运算,对集合有要求吗?)
有要求的:参与运算的各个集合必须列数相同且类型一致
PL: emp10 = filter emp2 by deptno==10;
emp20 = filter emp2 by deptno==20;
执行集合运算: emp10_20 = union emp10,emp20;
10、使用PL实现WC
前4步 都不会触发计算
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的自定义函数 : 类似Hive的自定义函数,也是Java程序
使用:注册jar包
把pig包下lib里的jar和pig-0.17.0-core-h2.jar 放导入引用,主要是h2 包 ,hadoop2-runtime包
1、自定义过滤函数: 把满足条件的记录选择出来
eg:查询工资大于2000块钱的员工
2、自定义运算函数
eg: 根据员工的薪水来判断薪水的级别
注册 函数 到 pig register /root/temp/p2.jar
使用自己的pig函数
查看 结构 : describe records;
打印出来: dump records;
3、自定义加载函数(最麻烦)
tuple 嵌套表 表里包含 行,pig特有的结构
用到的是MapReduce的jar
导包的时候注意使用MapReduce的jar
行里嵌套表
import java.io.IOException;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapreduce.InputFormat;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.pig.LoadFunc;
import org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigSplit;
import org.apache.pig.data.BagFactory;
import org.apache.pig.data.DataBag;
import org.apache.pig.data.Tuple;
import org.apache.pig.data.TupleFactory;
/*
* 实现自己的加载函数:每个单词作为一个Tuple,然后把这些Tuple放入一个bag中,再把这个bag放入tuple
*/
public class MyLoadFunc extends LoadFunc {
//定义一个变量来保存HDFS的输入流
private RecordReader reader;
@Override
public InputFormat getInputFormat() throws IOException {
//输入数据的格式是什么: 字符串
return new TextInputFormat();
}
@Override
public Tuple getNext() throws IOException {
//从输入流中读入了数据,如何进行加载,加载完后,返回tuple
//数据: I love Beijing ---> 每个单词作为一个Tuple
Tuple result = null;
try{
//判断是否读入了数据
if(!this.reader.nextKeyValue()){
//如果是false,就么有读取到数据
return result; //----> null值
}
//读到了数据,进行加载
//数据 I love Beijing
String data = this.reader.getCurrentValue().toString();
//生成结果的Tuple
result = TupleFactory.getInstance().newTuple();
//分词
String[] words = data.split(" ");
//1 把每个单词放入一个Tuple,再把这些tuple放入一个bag中
//创建一个bag
DataBag bag = BagFactory.getInstance().newDefaultBag();// 生成表
for(String w:words){
// 2 为每个单词生成Tuple
Tuple aTuple = TupleFactory.getInstance().newTuple();
aTuple.append(w);//加入单词
// 3 把aTuple加入表
bag.add(aTuple);
}
// 4 把表放入result的tuple中
result.append(bag);
}catch(Exception ex){
ex.printStackTrace();
}
return result;
}
@Override
public void prepareToRead(RecordReader reader, PigSplit arg1) throws IOException {
// reader: 代表HDFS的输入流
//使用reader来读取数据
this.reader = reader;
}
@Override
public void setLocation(String path, Job job) throws IOException {
// 指定HDFS输入的路径
FileInputFormat.setInputPaths(job, new Path(path));
}
}
执行结果
至此数据分析的引擎 MapReduce 和 hive 已经 讲完 ,下面开始讲 数据采集的 引擎 sqoop he Flume
Impala与Hive在Hadoop中的关系如下图
Hive适合于长时间的批处理查询分析,而Impala适合于实时交互式SQL查询,Impala给数据分析人员提供了快速实验、验证想法的大数 据分析工具。可以先使用hive进行数据转换处理,之后使用Impala在Hive处理后的结果数据集上进行快速的数据分析。