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的安装过程很简单,网上有很多安装方式:
2 | [root@192.168.1.111] cd /opt/hadoop |
4 | [root@192.168.1.111] wget http://www.apache.org/dist/hadoop/hive/hive-0.5.0/hive-0.5.0-dev. tar .gz |
6 | [root@192.168.1.111] tar xzvf hive-0.5.0-dev. tar .gz |
8 | [root@192.168.1.111] cd hive-0.5.0-dev |
10 | [root@192.168.1.111] export HIVE_HOME=` pwd ` |
配置
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使用示例:
2 | create external table foo |
7 | row format delimited fields terminated by '\001' |
9 | location "/group/tbsc-dev/haowen/temp/shpsrch_bshop_brand_value_ssmerge_1011/" ; |
12 | INSERT OVERWRITE TABLE foo |
16 | select t1.uid,t2.value_data |
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 |
也可以在终端界面这样使用
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 |
4 | set mapred.reduce.tasks=1; |
5 | add file /data/tiechou/ssmerge/mod/mod_bshop_brand/script/brand_packed.pl; |
7 | INSERT OVERWRITE TABLE foo |
8 | select transform(uid, value_data) |
9 | using 'brand_packed.pl' |
13 | select t1.uid,t2.value_data |
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 |
19 | set mapred.reduce.tasks=256; |
上面显然不是最好的办法,不过已经说明问题了,是相同uid被分到多个namenode上join引起的,其实hive是支持clusterBy? | distributeBy? sortBy? 的, clusterBy是 distributeBy? sortBy?的综合
1 | hive -u root -p root <<EOF |
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' |
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会产生什么样的结果。
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
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
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值取代。
3 | ON TableA.name = TableB.name |
hive 中实现方式
2 | select a. id as a_id,b.del_id as b_id |
3 | from shop a left outer join del b |
id name id name
– —- — —-
2 Monkey null null
4 Spaghetti null null
结果集: 产生在A表中有而在B表中没有的集合。
3 | ON TableA.name = TableB.name |
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的组合,即笛卡尔积。表达式如下:
这个笛卡尔乘积会产生 4 x 4 = 16 条记录,一般来说,我们很少用到这个语法。但是我们得小心,如果不是使用嵌套的select语句,一般系统都会产生笛卡尔乘积然再做过滤。这是对于性能来说是非常危险的,尤其是表很大的时候。