Hive的基本原理与使用

本文转自:http://tiechou.info/?p=33

简介

Hive是基于Hadoop构建的一套数据仓库分析系统,它提供了丰富的SQL查询方式来分析存储在Hadoop 分布式文件系统中的数据。Hive可以将结构化的数据存储在数据仓库中,通过自己的SQL去查询分析需要的内容,这套SQL简称Hive SQL。它与关系型数据库的SQL略有不同,但支持了绝大多数的语句如DDL、DML 以及常见的聚合函数、连接查询、条件查询。

Hive在Hadoop的架构体系中承担了一个SQL解析的过程,它提供了对外的入口来获取用户的指令然后对指令进行分析,解析出一个MapReduce程序组成可执行计划,并按照该计划生成对应的MapReduce任务提交给Hadoop集群处理,获取最终的结果。
安装

Hive需要Hadoop的支持,也就是说在安装Hive之前需要正确安装Hadoop。一般我们会将Hive安装到NameNode所在主机上,这里假设使用root用户进行安装,Hive的安装过程很简单,网上有很多安装方式:

1 [[email protected]] # 去到hadoop的目录,使用hadoop的项目根目录
2 [[email protected]] cd /opt/hadoop
3 [[email protected]] # 下载项目包(去官网(http://hadoop.apache.org/)下载Hadoop项目)
5 [[email protected]] # 解压
6 [[email protected]] tar xzvf hive-0.5.0-dev.tar.gz
7 [[email protected]] # 进入目录
8 [[email protected]] cd hive-0.5.0-dev
9 [[email protected]] # 与Hadoop的安装一样,我们应该习惯性的将安装目录写入环境变量
10 [[email protected]] export HIVE_HOME=`pwd`
11 [[email protected]] # 也可以将环境变量设置到/etc/profile中


配置

Hive的必要配置相当简单,只需要声明$HADOOP_HOME(请查阅《Hadoop安装》文档)这个环境变量就行了。

Hive的核心配置文件$HIVE_HOME/conf/hive-default.xml中有一些对Hive关键配置,一般我们不需要对期进行改动,如果你需要更改这个关键配置,请不要直接更改hive-default.xml这个文件,在同一目录下新建hive-site.xml文件,然后将需要更改的属性配置在这里面即可,配置格式与hive-default.xml一样。

在Hive官方文档中重点提到了Hive的日志配置$HIVE_HOME/conf/hive-log4j.properties,虽然不是必要更改的配置文件,但合理的设置会对我们有一定的帮助,具体配置方法可见官方文档。


使用

Hive提供了一个CLI(Command Line Interface)客户端,我们可以通过CLI进行直观的DDL、DML及SQL操作。以下是CLI使用示例:

1 # 这里创建了一个foo表,字段以\001分隔,location指定映射文件位置
2 create external table foo
3 (
4 uid bigint,
5 brand_value string
6 )
7 row format delimited fields terminated by '\001'
8 stored as textfile
9 location "/group/tbsc-dev/haowen/temp/shpsrch_bshop_brand_value_ssmerge_1011/";
10   
11 # 插入数据到 foo表 注意这些语句不要用tab缩进
12 INSERT OVERWRITE TABLE foo
13 select uid,value_data
14 from
15 (
16   select t1.uid,t2.value_data
17   from
18      shpsrch_bshop_brand_unfold_ssmerge_1011 t1
19      join sel_shpsrch__base_values t2
20      on t1.brand_id = t2.value_id and t2.ds=20101019
21 ) a;

也可以在终端界面这样使用

1 echo "select * from foo where uid=153702175;" | hive -u root -p root


数据join

之前在数据join的时候遇到过这样一个问题,就是当一个uid 对应多个品牌brand_id 的时候,即:
uid – brand_id1 = brand_id1 – brand_value1
uid – brand_id2 = :
uid – brand_id3 = :
这样join之后的数据会出现:
uid – brand_value1
uid – brand_value1
这个样子相同的多条记录,出现数据重复的现象
如果数据量小的话,最简单的调试办法是 这样:把所有的数据放在一个namenode上面跑

1 hive -u root -p root  <<EOF
2   
3 # 指定reduced的任务数量
4 set mapred.reduce.tasks=1;
5 add file /data/tiechou/ssmerge/mod/mod_bshop_brand/script/brand_packed.pl;
6 explain
7 INSERT OVERWRITE TABLE foo
8   select transform(uid, value_data)
9   using 'brand_packed.pl'
10   as uid,brand_value
11   from
12 (
13 select t1.uid,t2.value_data
14   from
15      shpsrch_bshop_brand_unfold_ssmerge_1011 t1
16      join sel_shpsrch__base_values t2
17      on t1.brand_id = t2.value_id and t2.ds=1 distribute by t1.uid
18 ) a;
19 set mapred.reduce.tasks=256;
20 EOF

上面显然不是最好的办法,不过已经说明问题了,是相同uid被分到多个namenode上join引起的,其实hive是支持clusterBy? | distributeBy? sortBy? 的, clusterBy是 distributeBy? sortBy?的综合

1 hive -u root -p root  <<EOF
2   
3 add file /data/tiechou/ssmerge/mod/mod_bshop_brand/script/brand_packed.pl;
4 INSERT OVERWRITE TABLE foo
5 select transform(t3.uid,t3.value_data)
6   using 'brand_packed.pl'
7   as uid,brand_value
8 from(
9 from shpsrch_bshop_brand_unfold_ssmerge_1011 t1 join sel_shpsrch__base_values t2 on (t1.brand_id = t2.value_id and t2.ds=20101019) select t1.uid,t2.value_data distribute by t1.uid) t3;

最后我们普及一下sql join,在网上找了一个很形象的说明:http://coolshell.cn/articles/3463.html

SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚。Coding Horror上有一篇文章(实在不清楚为什么Coding Horror也被墙)通过 文氏图 Venn diagrams 解释了SQL的Join。


假设我们有两张表。

Table A 是左边的表。

Table B 是右边的表。


其各有四条记录,其中有两条记录是相同的,如下所示:


id name id name

– —- — —-
1 Pirate 1 Rutabaga
2 Monkey 2 Pirate
3 Ninja 3 Darth Vader
4 Spaghetti 4 Ninja


下面让我们来看看不同的Join会产生什么样的结果。

1 SELECT * FROM TableA
2 INNER JOIN TableB
3 ON TableA.name = TableB.name


Inner join

id name id name
– —- — —-
1 Pirate 2 Pirate
3 Ninja 4 Ninja
结果集: 是A和B的交集。


Full outer join

1 SELECT * FROM TableA
2 FULL OUTER JOIN TableB
3 ON TableA.name = TableB.name


id name id name
– —- — —-
1 Pirate 2 Pirate
2 Monkey null null
3 Ninja 4 Ninja
4 Spaghetti null null
null null 1 Rutabaga
null null 3 Darth Vader


结果集: 产生A和B的并集。但是需要注意的是,对于没有匹配的记录,则会以null做为值。


Left outer join

1 SELECT * FROM TableA
2 LEFT OUTER JOIN TableB
3 ON TableA.name = TableB.name


id name id name
– —- — —-
1 Pirate 2 Pirate
2 Monkey null null
3 Ninja 4 Ninja
4 Spaghetti null null


Left outer join 产生表A的完全集,而B表中匹配的则有值,没有匹配的则以null值取代。

1 SELECT * FROM TableA
2 LEFT OUTER JOIN TableB
3 ON TableA.name = TableB.name
4 WHERE TableB.id IS null


hive 中实现方式

1 select a_id from (
2 select a.id as a_id,b.del_id as b_id
3 from shop a left outer join del b
4 on a.id = b.del_id )c
5 where b_id is null;


id name id name
– —- — —-
2 Monkey null null
4 Spaghetti null null


结果集: 产生在A表中有而在B表中没有的集合。

1 SELECT * FROM TableA
2 FULL OUTER JOIN TableB
3 ON TableA.name = TableB.name
4 WHERE TableA.id IS null
5 OR TableB.id IS null


id name id name
– —- — —-
2 Monkey null null
4 Spaghetti null null
null null 1 Rutabaga
null null 3 Darth Vader


结果集: 产生A表和B表都没有出现的数据集。

还需要注册的是我们还有一个是“交差集” cross join, 这种Join没有办法用文式图表示,因为其就是把表A和表B的数据进行一个N*M的组合,即笛卡尔积。表达式如下:

1 SELECT * FROM TableA
2 CROSS JOIN TableB

这个笛卡尔乘积会产生 4 x 4 = 16 条记录,一般来说,我们很少用到这个语法。但是我们得小心,如果不是使用嵌套的select语句,一般系统都会产生笛卡尔乘积然再做过滤。这是对于性能来说是非常危险的,尤其是表很大的时候。

猜你喜欢

转载自yeshuqiang.iteye.com/blog/1153247