基于Hadoop的数据仓库Hive 学习指南

添加时间:2016-2-22 16:03:05 编辑:罗建东 阅读:203


本指南介绍了Hive,并详细指引读者安装Hive。 前面第几章学习指南已经指导大家安装Linux操作系统,并安装配置了Hadoop,但是这只表明我们已经安装好了Hadoop分布式文件系统,而Hive需要另外下载安装,本指南就是详细指导大家安装并配置Hive,完成后大家可以结合厦门大学林子雨开设的《大数据技术原理与应用》课程第14章节进行深入学习。

一、Hive简介

Hive是Facebook开发的构建于Hadoop集群之上的数据仓库应用,可以将结构化的数据文件映射为一张数据库表,并提供完整的SQL查询功能,可以将SQL语句转换为MapReduce任务进行运行。

Hive是一个可以提供有效的、合理的且直观的组织和使用数据的模型,即使对于经验丰富的Java开发工程师来说,将这些常见的数据运算对应到底层的MapReduce Java API也是令人敬畏的。Hive可以帮用户做这些工作,用户就可以集中精力关注查询本身了。Hive可以将大多数的查询转换为MapReduce任务。Hive最适合于数据仓库应用程序,使用该应用程序进行相关的静态数据分析,不需要快速响应给出结果,而且数据本身也不会频繁变化。

Hive不是一个完整的数据库。Hadoop以及HDFS的设计本身约束和局限性限制了Hive所能胜任的工作。最大的限制就是Hive不支持记录级别的更新、插入或者删除。用户可以通过查询生成新表或将查询结果导入到文件中去。因为,Hadoop是一个面向批处理的系统,而MapReduce启动任务启动过程需要消耗很长时间,所以Hive延时也比较长。Hive还不支持事务。因此,Hive不支持联机事务处理(OLTP),更接近于一个联机分析技术(OLAP)工具,但是,目前还没有满足“联机”部分。

Hive提供了一系列的工具,可以用来进行数据提取转化加载(ETL),其中,ETL是一种可以存储、查询和分析存储在Hadoop中的大规模数据的机制。因此,Hive是最适合数据仓库应用程序的,它可以维护海量数据,而且可以对数据进行挖掘,然后形成意见和报告等。

因为大多数的数据仓库应用程序是基于SQL的关系数据库现实的,所以,Hive降低了将这些应用程序移植到Hadoop上的障碍。如果用户懂得SQL,那么学习使用Hive会很容易。因为Hive定义了简单的类SQL 查询语言——HiveQL,这里值得一提的是,与SQLServer、Oracle相比,HiveQL和MySQL提供的SQL语言更接近。同样的,相对于其他的Hadoop语言和工具来说,Hive也使得开发者将基于SQL的应用程序移植到Hadoop变得更加容易。

二、Hive安装

因为Hive是构建在Hadoop之上的,所以在安装Hive前,我们需要安装Hadoop环境。Hadoop的安装可以参照厦门大学数据库实验室网站上的安装教程(http://dblab.xmu.edu.cn/blog/install-hadoop/-simplify),但是,请注意,在按照该教程安装完Hadoop以后,不要进行配置,Hadoop的配置过程,稍后我们在安装完Hive后一起进行。

下面开始安装Hive。

安装Hive的过程和安装Hadoop很类似,首先,我们先下载一个Hive软件压缩包(下载地址:http://www.apache.org/dyn/closer.cgi/hive/),然后进行解压缩,具体如下:

	
	
  1. cd ~/下载
  2. sudo tar -zxvf ./apache-hive-1.2.1-bin.tar.gz -C /usr/local # 解压到/usr/local中
  3. cd /usr/local/
  4. sudo mv ./apache-hive-1.2.1-bin/ ./hive # 将文件夹名改为hive
  5. sudo chown -R hadoop:hadoop ./hive # 修改文件权限
  6. sudo mkdir -p /usr/local/hive/warehouse # 创建元数据存储文件夹
  7. sudo chmod a+rwx /usr/local/hive/warehouse # 修改文件权限
Shell

为了方便使用,我们把hive命令加入到环境变量中去,需要使用以下命令编辑.bashrc文件:

	
	
  1. vim ~/.bashrc # 设置环境变量
Shell

进入.bashrc编辑状态以后,需要在文件最前面添加如下几行:

export HIVE_HOME=/usr/local/hive
export PATH=$PATH:$HIVE_HOME/bin

完成上述操作后,需要运行以下命令让配置生效:

	
	
  1. source ~/.bashrc # 使配置立即生效
Shell

然后运行hive命令启动Hive,命令如下:

	
	
  1. hive # 启动Hive
Shell

当出现以下界面即为启动成功。

Hive启动失败

若启动不成功,则会出现以下错误:

则需要进入到hadoop安装目录下的share/hadoop/yarn/lib下删除jline-0.9.94.jar文件,再启动hive即可(因为高版本的Hadoop对Hive有捆绑)。

三、 Hive配置

通过Hadoop的学习我们已经知道,Hadoop的运行模式有三种:本地模式、伪分布式模式和分布式模式。这里我们以介绍本地模式为主,其他模式只进行简单介绍。因为,本地模式是Hadoop的默认模式,所以,Hadoop不需要进行其他配置,我们只需对Hive进行相应配置。这里只需修改hive-site.xml文件,如果该文件不存在,用户需要自己新建一个。(注意:在$HIVE_HOME/conf目录下我们可能会看到hive-default.xml.template这个大文件,这个文件中包含了Hive提供的配置属性以及默认的属性值,这些属性中的绝大多数,用户可以忽略不管)。

在安装Hive时,默认情况下,元数据存储在Derby数据库中。Derby是一个完全用Java编写的数据库,所以可以跨平台,但需要在JVM中运行 。因为多用户和系统可能需要并发访问元数据存储,所以默认的内置数据库并不适用于生产环境。任何一个适用于JDBC进行连接的数据库都可用作元数据库存储,这里我们把MySQL作为存储元数据的数据库。接下来,我们分别对这两种方式进行介绍,即使用Derby数据库的方式和使用MySQL数据库的方式。

使用Derby数据库的方式

本地模式中,用户的“表”等元数据信息,都默认存储在file://user/hive/warehouse,对于其他模式默认存储路径是hdfs://namenode_server/user/hive/warehouse。使用如下命令编辑hive-site.xml文件:

	
	
  1. vim /usr/local/hive/conf/hive-site.xml
Shell

在hive-site.xml文件添加以下内容:

	
	
  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
  3. <configuration>
  4. <property>
  5. <name>hive.metastore.warehouse.dir</name>
  6. <value>/usr/local/hive/warehouse</value>
  7. <description>location of default database for the warehouse</description>
  8. </property>
  9. <property>
  10. <name>javax.jdo.option.ConnectionURL</name>
  11. <value>jdbc:derby:;databaseName=/usr/local/hive/metastore_db;create=true</value>
  12. <description>JDBC connect string for a JDBC metastore</description>
  13. </property>
  14. </configuration>
XML

伪分布式模式和分布式模式配置Hive,只需根据Hadoop配置文件core-site.xml中fs.defaultFS的值对hive.metastore.warehouse.dir 进行相应修改即可。这里对Hadoop的模式配置,可以参考厦门大学数据库实验室网站上的的配置教程(http://dblab.xmu.edu.cn/blog/install-hadoop-simplify

Hive配置完成后,下面来启动它,并使用简单的HiveQL命令进行相应测试。我们先新建了一个表x,它有1个int型属性a,然后查找表x中的所有属性,最后删除表x,然后退出。HiveQL命令与SQL命令很相似,所以,读者如果有SQL基础的话,会很快上手。关于HiveQL命令的使用方法会在第4节详细介绍。

注意,命令最后需要以分号“;”结束

使用MySQL数据库的方式

1)首先我们需要安装MySQL(如果本机上已经安装MySQL,请跳过此步骤)。可以参考网址(http://dev.mysql.com/downloads/mysql/)进行下载安装,也可以用apt-get 命令下载,这里我们选择后者。

a.查看并卸载系统自带的MySQL相关安装包,命令如下:

	
	
  1. rpm -qa|grep mysql
Shell

若没有安装rpm工具,系统会有提示,按照提示安装即可。接下来查看是否有系统自带的MySQL相关安装包,若有,按下面命令删除:

	
	
  1. sudo rpm -e --nodeps mysql-libs-xxxxxx
Shell

b.安装MySQL,命令如下:

	
	
  1. sudo apt-get install mysql-server
Shell

c. 启动设置MySQL,命令如下:

	
	
  1. sudo service mysql start #启动mysql服务
  2. sudo chkconfig mysql on #设置为开机自启动
  3. sudo /usr/bin/mysqladmin -u root password '123' #设置root用户登录密码
  4. mysql -u root -p #登录mysql
Shell

d. 创建hive用户,数据库等,命令如下:

	
	
  1. insert into mysql.user (Host,User,Password) values ("localhost","hive",password (" hive")); # 创建hive用户
  2. create database hive; # 创建hive数据库
  3. grant all on hive.* to hive@'%' identified by 'hive';
  4. grant all on hive.* to hive@'localhost' identified by 'hive';
  5. flush privileges;
  6. exit #退出mysql
  7.  
  8. mysql -u hive -p hive #验证hive用户
  9.  
  10. show databases;
Shell

看到以下信息,则说明创建成功。

2)配置Hive,修改hive-site.xml文件,修改后的结果如下:

	
	
  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
  3. <configuration>
  4. <property>
  5. <name>hive.metastore.warehouse.dir</name>
  6. <value>/usr/local/hive/warehouse</value>
  7. <description>location of default database for the warehouse</description>
  8. </property>
  9. <property>
  10. <name>javax.jdo.option.ConnectionURL</name>
  11. <value>jdbc:mysql://localhost:3306/hive;createDatebaseIfNotExist=true</value>
  12. <description>JDBC connect string for a JDBC metastore</description>
  13. </property>
  14. <property>
  15. <name>javax.jdo.option.ConnectionDriverName</name>
  16. <value>com.mysql.jdbc.Driver</value>
  17. <description>Driver class name for a JDBC metastore</description>
  18. </property>
  19. <property>
  20. <name>javax.jdo.option.ConnectionPassword </name>
  21. <value>hive </value>
  22. </property>
  23. <property>
  24. <name>javax.jdo.option.ConnectionUserName</name>
  25. <value>hive</value>
  26. <description>Username to use against metastore database</description>
  27. </property>
  28. </configuration>
XML

修改完hive-site.xml文件后,我们需要把JDBC驱动放置在lib目录下(JDBC驱动程序mysql-connector-java-x.x.x-bin.jar文件的下载地址为http://www.mysql.com/downloads/connector/j/ ),命令如下:

	
	
  1. mv ~/下载/mysql-connector-java-5.1.30-bin.jar /usr/local/hive /lib/ #拷贝mysql-connector-java-5.1.30-bin.jar 到hive 的lib下
  2. cp /usr/local/hive/lib/jline-2.12.jar /usr/local/hadoop /share/ hadoop/yarn/lib # 把jline-2.12.jar拷贝到hadoop相应目录下
  3. mkdir -p /usr/local/hive/tmp #创建hive临时文件夹
  4. sudo chmod a+rwx /usr/local/hive/tmp # 修改文件权限
Shell 命令

接下来,启动测试Hive。首先启动Hadoop后,执行Hive命令 hive,并输入 show databases; 进行测试。

hive client常用命令可以通过 hive --help 查看。下面再介绍一些hive client常用命令,用户可以自行测试:

	
	
  1. show tables; #查看所有表名
  2. show tables 'ad*' ; #查看以'ad'开头的表名
  3. set 命令 #设置变量与查看变量
  4. set v; #查看所有的变量
  5. set hive.stats.atomic; #查看hive.stats.atomic变量
  6. set hive.stats.atomic=false; #设置hive.stats.atomic变量
  7. dfs -ls ; #查看hadoop所有文件路径
  8. dfs -ls /usr/local/hive/warehouse/; #查看hive所有文件
  9. source file <filepath> #在client里执行一个hive脚本文件
  10. quit; #退出交互式shell
  11. exit #退出交互式shell
  12. reset #重置配置为默认值
  13. !ls #从Hive shell执行一个shell命令
sql

四、Hive的常用HiveQL操作

1)Hive基本数据类型

首先,我们简单叙述一下HiveQL的基本数据类型。

Hive支持基本数据类型和复杂类型, 基本数据类型主要有数值类型(INT、FLOAT、DOUBLE ) 、布尔型和字符串, 复杂类型有三种:ARRAY、MAP 和 STRUCT。

a.基本数据类型

  • TINYINT: 1个字节
  • SMALLINT: 2个字节
  • INT: 4个字节
  • BIGINT: 8个字节
  • BOOLEAN: TRUE/FALSE
  • FLOAT: 4个字节,单精度浮点型
  • DOUBLE: 8个字节,双精度浮点型STRING 字符串

b.复杂数据类型

  • ARRAY: 有序字段
  • MAP: 无序字段
  • STRUCT: 一组命名的字段

2)常用的HiveQL操作命令

Hive常用的HiveQL操作命令主要包括:数据定义、数据操作。接下来详细介绍一下这些命令即用法(想要了解更多请参照《Hive编程指南》一书)。

a.数据定义:主要用于创建修改和删除数据库、表、视图、函数和索引。

创建、修改和删除数据库

	
	
  1. create database if not exists hive; #创建数据库
  2. show databases; #查看Hive中包含数据库
  3. show databases like 'h.*'; #查看Hive中以h开头数据库
  4. describe databases; #查看hive数据库位置等信息
  5. alter database hive set dbproperties; #为hive设置键值对属性
  6. use hive; #切换到hive数据库下
  7. drop database if exists hive; #删除不含表的数据库
  8. drop database if exists hive cascade; #删除数据库和它中的表
sql

注意,除 dbproperties属性外,数据库的元数据信息都是不可更改的,包括数据库名和数据库所在的目录位置,没有办法删除或重置数据库属性。

创建、修改和删除表

	
	
  1. #创建内部表(管理表)
  2. create table if not exists hive.usr(
  3. name string comment 'username',
  4. pwd string comment 'password',
  5. address struct<street:string,city:string,state:string,zip:int>,
  6. comment 'home address',
  7. identify map<int,tinyint> comment 'number,sex')
  8. comment 'description of the table'
  9. tblproperties('creator'='me','time'='2016.1.1');
  10. #创建外部表
  11. create external table if not exists usr2(
  12. name string,
  13. pwd string,
  14. address struct<street:string,city:string,state:string,zip:int>,
  15. identify map<int,tinyint>)
  16. row format delimited fields terminated by ','
  17. location '/usr/local/hive/warehouse/hive.db/usr';
  18. #创建分区表
  19. create table if not exists usr3(
  20. name string,
  21. pwd string,
  22. address struct<street:string,city:string,state:string,zip:int>,
  23. identify map<int,tinyint>)
  24. partitioned by(city string,state string);
  25. #复制usr表的表模式
  26. create table if not exists hive.usr1 like hive.usr;
  27.  
  28. show tables in hive;
  29. show tables 'u.*'; #查看hive中以u开头的表
  30. describe hive.usr; #查看usr表相关信息
  31. alter table usr rename to custom; #重命名表
  32.  
  33. #为表增加一个分区
  34. alter table usr2 add if not exists
  35. partition(city=”beijing”,state=”China”)
  36. location '/usr/local/hive/warehouse/usr2/China/beijing';
  37. #修改分区路径
  38. alter table usr2 partition(city=”beijing”,state=”China”)
  39. set location '/usr/local/hive/warehouse/usr2/CH/beijing';
  40. #删除分区
  41. alter table usr2 drop if exists partition(city=”beijing”,state=”China”)
  42. #修改列信息
  43. alter table usr change column pwd password string after address;
  44.  
  45. alter table usr add columns(hobby string); #增加列
  46. alter table usr replace columns(uname string); #删除替换列
  47. alter table usr set tblproperties('creator'='liming'); #修改表属性
  48. alter table usr2 partition(city=”beijing”,state=”China”) #修改存储属性
  49. set fileformat sequencefile;
  50. use hive; #切换到hive数据库下
  51. drop table if exists usr1; #删除表
  52. drop database if exists hive cascade; #删除数据库和它中的表
sql

视图和索引的创建、修改和删除

主要语法如下,用户可自行实现。

	
	
  1. create view view_name as....; #创建视图
  2. alter view view_name set tblproperties(…); #修改视图
sql

因为视图是只读的,所以 对于视图只允许改变元数据中的 tblproperties属性。

	
	
  1. #删除视图
  2. drop view if exists view_name;
  3. #创建索引
  4. create index index_name on table table_name(partition_name/column_name)
  5. as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild....;
sql

这里’org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler’是一个索引处理器,即一个实现了索引接口的Java类,另外Hive还有其他的索引实现。

	
	
  1. alter index index_name on table table_name partition(...) rebulid; #重建索引
sql

如果使用 deferred rebuild,那么新索引成空白状态,任何时候可以进行第一次索引创建或重建。

	
	
  1. show formatted index on table_name; #显示索引
  2. drop index if exists index_name on table table_name; #删除索引
sql

用户自定义函数

在新建用户自定义函数(UDF)方法前,先了解一下Hive自带的那些函数。show functions; 命令会显示Hive中所有的函数名称:

若想要查看具体函数使用方法可使用describe function 函数名:

首先编写自己的UDF前需要继承UDF类并实现evaluate()函数,或是继承GenericUDF类实现initialize()函数、evaluate()函数和getDisplayString()函数,还有其他的实现方法,感兴趣的用户可以自行学习。

另外,如果用户想在Hive中使用该UDF需要将我们编写的Java代码进行编译,然后将编译后的UDF二进制类文件(.class文件)打包成一个JAR文件,然后在Hive会话中将这个JAR文件加入到类路径下,在通过create function语句定义好使用这个Java类的函数。

	
	
  1. add jar <jar文件的绝对路径>; #创建函数
  2. create temporary function function_name;
  3. drop temporary function if exists function_name; #删除函数
sql

3)数据操作

主要实现的是将数据装载到表中(或是从表中导出),并进行相应查询操作,对熟悉SQL语言的用户应该不会陌生。

向表中装载数据

这里我们以只有两个属性的简单表为例来介绍。首先创建表stu和course,stu有两个属性id与name,course有两个属性cid与sid。

	
	
  1. create table if not exists hive.stu(id int,name string)
  2. row format delimited fields terminated by '\t';
  3. create table if not exists hive.course(cid int,sid int)
  4. row format delimited fields terminated by '\t';
sql

向表中装载数据有两种方法:从文件中导入和通过查询语句插入。

a.从文件中导入

假如这个表中的记录存储于文件stu.txt中,该文件的存储路径为usr/local/hadoop/examples/stu.txt,内容如下。

stu.txt:

1 xiapi 
2 xiaoxue 
3 qingqing

下面我们把这个文件中的数据装载到表stu中,操作如下:

	
	
  1. load data local inpath '/usr/local/hadoop/examples/stu.txt' overwrite into table stu;
sql

如果stu.txt文件存储在HDFS 上,则不需要 local 关键字。

b.通过查询语句插入

使用如下命令,创建stu1表,它和stu表属性相同,我们要把从stu表中查询得到的数据插入到stu1中:

	
	
  1. create table stu1 as select id,name from stu;
sql

上面是创建表,并直接向新表插入数据;若表已经存在,向表中插入数据需执行以下命令:

	
	
  1. insert overwrite table stu1 select id,name from stu where(条件);
sql

这里关键字overwrite的作用是替换掉表(或分区)中原有数据,换成into关键字,直接追加到原有内容后。

从表中导出数据

a.可以简单拷贝文件或文件夹

命令如下:

	
	
  1. hadoop fs -cp source_path target_path;
Shell

b.写入临时文件

命令如下:

	
	
  1. insert overwrite local directory '/usr/local/hadoop/tmp/stu' select id,name from stu;
sql

查询操作

和SQL的查询完全一样,这里不再赘述。主要使用select…from…where…等语句,再结合关键字group by、having、like、rlike等操作。这里我们简单介绍一下SQL中没有的case…when…then…句式、join操作和子查询操作。

case…when…then…句式和if条件语句类似,用于处理单个列的查询结果,语句如下:

	
	
  1. select id,name,
  2. case
  3. when id=1 then 'first'
  4. when id=2 then 'second'
  5. else 'third'
sql

结果如下:

连接
连接(join)是将两个表中在共同数据项上相互匹配的那些行合并起来, HiveQL 的连接分为内连接、左向外连接、右向外连接、全外连接和半连接 5 种。

a. 内连接(等值连接)
内连接使用比较运算符根据每个表共有的列的值匹配两个表中的行。

首先,我们先把以下内容插入到course表中(自行完成)。

1 3
2 1
3 1

下面, 查询stu和course表中学号相同的所有行,命令如下:

	
	
  1. select stu.*, course.* from stu join course on(stu .id=course .sid);
sql

执行结果如下:

b. 左连接
左连接的结果集包括“LEFT OUTER”子句中指定的左表的所有行, 而不仅仅是连接列所匹配的行。如果左表的某行在右表中没有匹配行, 则在相关联的结果集中右表的所有选择列均为空值,命令如下:

	
	
  1. select stu.*, course.* from stu left outer join course on(stu .id=course .sid);
sql

执行结果如下:

c. 右连接
右连接是左向外连接的反向连接,将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。命令如下:

	
	
  1. select stu.*, course.* from stu right outer join course on(stu .id=course .sid);
sql

执行结果如下:

d. 全连接
全连接返回左表和右表中的所有行。当某行在另一表中没有匹配行时,则另一个表的选择列表包含空值。如果表之间有匹配行,则整个结果集包含基表的数据值。命令如下:

	
	
  1. select stu.*, course.* from stu full outer join course on(stu .id=course .sid);
sql

执行结果如下:

e. 半连接
半连接是 Hive 所特有的, Hive 不支持 in 操作,但是拥有替代的方案; left semi join, 称为半连接, 需要注意的是连接的表不能在查询的列中,只能出现在 on 子句中。命令如下:

	
	
  1. select stu.* from stu left semi join course on(stu .id=course .sid);
sql

执行结果如下:

子查询
标准 SQL 的子查询支持嵌套的 select 子句,HiveQL 对子查询的支持很有限,只能在from 引导的子句中出现子查询。

注意,在定义或是操作表时,不要忘记指定所需数据库。

五、Hive简单编程实践

下面我们以词频统计算法为例,来介绍怎么在具体应用中使用Hive。词频统计算法又是最能体现MapReduce思想的算法之一,这里我们可以对比它在MapReduce中的实现,来说明使用Hive后的优势。

MapReduce实现词频统计的代码可以通过下载Hadoop源码后,在 $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.1.jar 包中找到(wordcount类),wordcount类由63行Java代码编写而成。下面首先简单介绍一下怎么使用MapReduce中wordcount类来统计单词出现的次数,具体步骤如下:

1)创建input目录,output目录会自动生成。其中input为输入目录,output目录为输出目录。命令如下:

	
	
  1. cd /usr/local/hadoop
  2. mkdir input
Shell

2)然后,在input文件夹中创建两个测试文件file1.txt和file2.txt,命令如下:

	
	
  1. cd /usr/local/hadoop/input
  2. echo "hello world" > file1.txt
  3. echo "hello hadoop" > file2.txt
Shell

3)执行如下hadoop命令:

	
	
  1. cd ..
  2. hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.4.1.jar wordcount input output
Shell

4)我们可以到output文件夹中查看结果,结果如下:

下面我们通过HiveQL实现词频统计功能,此时只要编写下面7行代码,而且不需要进行编译生成jar来执行。HiveQL实现命令如下:

	
	
  1. create table docs(line string);
  2. load data inpath 'input' overwrite into table docs;
  3. create table word_count as
  4. select word, count(1) as count from
  5. (select explode(split(line,' '))as word from docs) w
  6. group by word
  7. order by word;
sql

执行后,用select语句查看,结果如下:

由上可知,采用Hive实现最大的优势是,对于非程序员,不用学习编写Java MapReduce代码了,只需要用户学习使用HiveQL就可以了,而这对于有SQL基础的用户而言是非常容易的。