转自:http://blog.csdn.net/zhoudaxia/article/details/8842576
1、安装与配置
Hive是建立在Hadoop上的数据仓库软件,用于查询和管理存放在分布式存储上的大规模数据集。它提供:
(1)一系列的工具,可以方便地对数据进行提取/转化/加载(ETL);
(2)一种可以对各种数据格式上进行结构化的机制;
(3)存取存放在Apache HDFS或其他存储系统如Apache HBase上的文件;
(4)通过MapReduce执行查询功能。
Hive 定义了简单的类SQL查询语言,称为QL,它允许熟悉SQL的用户查询数据。同时,这个语言也允许熟悉MapReduce的开发者开发自定义的mapper和reducer来处理内建的mapper和reducer无法完成的复杂分析工作。QL也可以被扩展,以让用户自定义标量函数(UDF's)、聚合(UDAF's)和表函数(UDTF's)。
Hive并不要求使用"Hive格式"来读写数据--没有这样的格式,Hive没有专门的数据格式。 Hive可以很好的工作在Apache Thrift、控制分隔符、或用户指定的数据格式上。
Hive并不是为OLTP工作负载设计的,也不提供实时查询和行级别的更新。它最常用于批量作业,比较适合工作在只追加的大数据集上(如Web日志)。Hive的核心设计思想是可伸缩性(通过动态添加到Hadoop集群的机器来进行横向扩展)、可扩展性(使用MapReduce框架和UDF/UDAF/UDTF)、容错性、与输入格式的松耦合性。
从http://hive.apache.org/releases.html处下载最新的稳定版hive-0.9.0.tar.gz。下一步你需要解压缩Tar包,这将会创建一个名为hive-x.y.z的子目录:
$ tar -xzvf hive-x.y.z.tar.gz
设置HIVE_HOME环境变量指向到Hive的安装目录:
$ cd hive-x.y.z
$ export HIVE_HOME=$(pwd)
最后,将$HIVE_HOME/bin添加到你的PATH环境变量中:
$ export PATH=$HIVE_HOME/bin:$PATH
2、运行Hive
Hive使用Hadoop,这意味着你必须在PATH里面设置了hadoop路径,或者导出export HADOOP_HOME=<hadoop-install-dir>也可以。另外,你必须在创建Hive库表前,在HDFS上创建/tmp和/user/hive/warehouse(也称为hive.metastore.warehouse.dir),并且将它们的权限设置为chmod g+w。完成这个操作的命令如下:
$ $HADOOP_HOME/bin/hadoop fs -mkdir /tmp
$ $HADOOP_HOME/bin/hadoop fs -mkdir /user/hive/warehouse
$ $HADOOP_HOME/bin/hadoop fs -chmod g+w /tmp
$ $HADOOP_HOME/bin/hadoop fs -chmod g+w /user/hive/warehouse
我同样发现设置HIVE_HOME是很重要的,但并非必须。
$ export HIVE_HOME=<hive-install-dir>
在Shell中使用Hive命令行(cli)模式:
$ $HIVE_HOME/bin/hive
3、配置文件管理概述
(1)Hive默认的配置文件保存在 <install-dir>/conf/hive-default.xml,你可以修改其中的配置,并重命名这个文件为 <install-dir>/conf/hive-site.xml(注:我建议你还是保留原始配置文件)。
(2)Hive配置文件的位置可以通过设置HIVE_CONF_DIR环境变量来改变。
(3)Log4j的配置保存在<install-dir>/conf/hive-log4j.properties。
(4)Hive的配置存在于Hadoop之上,这意味着Hadoop的配置默认会被继承到Hive中。
(5)Hive配置可以被如下方式控制:
编辑hive-site.xml并定义任何需要的变量 (包括hadoop的变量)
从cli模式使用使用set命令。使用如下方式:
$ bin/hive -hiveconf x1=y1 -hiveconf x2=y2
这个例子分别设置了变量x1为y1,x2为y2。设置使用 HIVE_OPTS环境变量 "-hiveconf x1=y1 -hiveconf x2=y2" 与上面的功能相同。
Hive查询是执行map-reduce查询,并且这些查询是可以被hadoop的配置所控制的。命令行命令 'SET' 可以被用来设置任何hadoop(或者hive)的配置变量,例如:
hive> SET mapred.job.tracker=myhost.mycompany.com:50030;
hive> SET -v;
后者SET -v用来查看当前全部的设置。而不使用 -v 选项,则是用来查看当前与Hadoop不同的配置。
4、Hive,Map-Reduce与本地模式
Hive编译器会为绝大多数查询生成map-reduce的jobs。这些Jobs使用下面这个变量来表明被提交到Map-Reduce集群中:
mapred.job.tracker
由于这通常是在一个多节点的map-reduce集群中被指出,Hadoop同样有个就近的方式来在用户的工作机上运行map-reduce jobs。这就在小数据集的查询上显得非常有用 - 在这种情况下,本地模式运行通常会比将任务提交到整个大集群中查询更快。数据从HDFS上获取是透明的。同样的,由于本地模式仅运行一个reducer,这样,在大数据查询上是非常慢的。
从0.7版本开始,Hive全面支持本地运行模式,要使用这个模式,请按照下列进行设置:
hive> SET mapred.job.tracker=local;
另外,mapred.local.dir应该指定一个合法的本机路径(注:安装hive的那台服务器)(例如:/tmp/<username>/mapred/local)。否则用户将获取一个定位本地空间的异常抛出)。
从0.7版本开始,Hive同样支持自动/非自动地使用本地模式来完成map-reduce jobs,相关的选项是:
hive> SET hive.exec.mode.local.auto=false;
请注意这个功能默认是关闭的,如果打开,Hive将分析每一个查询的map-reduce job,并且如果以下阀值被确认为OK,就尝试运行在本地:
(1)全部job的输入低于:hive.exec.mode.local.auto.inputbytes.max (128MB 默认)
(2)全部的map任务数低于:hive.exec.mode.local.auto.tasks.max (4 个默认)
(3)全部reduce任务数等于1或者0。
对于小数据集上的查询,或者带有多个map-reduce jobs的查询,但是这些job的输入是很小的(注:小于上述条件),jobs仍可能使用本地模式来运行。
注意,可能hadoop服务器节点和hive客户端的运行时环境不同(由于不同的jvm版本或者不同的软件库)。这可能会导致运行本地模式时出现一些意外的错误。同样需要注意的是,本地运行模式是运行在一个独立的子jvm中(hive 客户端的子进程)。如果用户愿意,子jvm所能使用的最大内存数可以通过选项hive.mapred.local.mem来进行控制。默认设置是0,这时Hive让Hadoop来决定子jvm的默认内存限制。
5、错误日志
Hive使用log4j来记录日志。默认来说,日志不会被返回到CLI模式的控制台上。默认的日志记录等级是WARN,并被保存到以下文件夹中:
/tmp/<user.name>/hive.log
如果用户愿意,日志可以通过修改下面的参数来返回到控制台上:
bin/hive -hiveconf hive.root.logger=INFO,console
另外,用户可以改变记录等级:
bin/hive -hiveconf hive.root.logger=INFO,DRFA
注意,配置项hive.root.logger在hive初始化以后,不能通过使用'set'命令来改变了。
Hive也会在在/tmp/<user.name>/ 下为每个hive会话保存查询日志,但是可以通过修改hive-site.xml中的hive.querylog.location属性来变更。
Hive在一个hadoop集群上的运行日志是由Hadoop的配置所决定的。通常Hadoop会为每个map和reduce任务创建日志文件,并保存在运行任务的集群服务器上。日志文件可以通过Hadoop Jobtracker提供的Web UI上的Task Detail页面来跟踪观察。
运行本地模式时(mapred.job.tracker=local),Hadoop/Hive会将执行日志放在本机上,从0.6版本开始,Hive使用hive-exec-log4j.properties (如果不存在,则是使用hive-log4j.properties文件)来决定默认日志的保存方式。默认的配置文件将为每个通过本地模式执行的查询生成一个日志,并存放到/tmp/<user.name>下。这样做的目的是为了将配置单独管理,并可以将日志集中存放到一个用户需要的位置上(例如一个NFS文件服务器)。执行日志对调试运行时错误并无帮助。
错误日志对于定位问题非常有用,请将存在的任何bug发送到hive-dev@hadoop.apache.org
6、DDL操作
创建Hive表和查看使用
hive> CREATE TABLE pokes (foo INT, bar STRING);
创建一个包含两个字段,名称为pokes的表,第一个字段是int(注:整型),第二个字段是string(注:字符串)
hive> CREATE TABLE invites (foo INT, bar STRING) PARTITIONED BY (ds STRING);
创建一个名为invites的表,其中包含两个字段和一个叫做ds的分区(partition)字段。分区字段是一个虚拟的字段,本身并不包含在数据中,但是是从加载进来的数据中特别衍生出来的数据集。
默认情况下,表被假定是纯文本的格式,并且使用^A(ctrl-a)来作为数据分割的。
hive> SHOW TABLES;
列出所有的表
hive> SHOW TABLES '.*s';
列出所有结尾包含 's' 的表名。匹配方式使用Java正则表达式,查看下列连接获取关于Java正则的信息http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html
hive> DESCRIBE invites;
查看invites表的全部字段
可以修改表名,增加删除新的字段等:
hive> ALTER TABLE pokes ADD COLUMNS (new_col INT);
hive> ALTER TABLE invites ADD COLUMNS (new_col2 INT COMMENT 'a comment');
hive> ALTER TABLE events RENAME TO 3koobecaf;
删除表:
hive> DROP TABLE pokes;
7、元数据存储
元数据默认使用Derby数据库保存在本地文件系统中,并保存在./metastore_db下。通过修改conf/hive-default.xml中的javax.jdo.option.ConnectionURL变量修改。
当前,在默认配置下,元数据每次只能同时被一个用户所使用。
元数据可以存储在任何一个使用JPOX支持的数据库中,这些关系型数据库的连接和类型可以通过两个变量进行控制。javax.jdo.option.ConnectionURL和javax.jdo.option.ConnectionDriverName。
你需要查看数据库的JDO(或JPOX)手册来获取更多信息。
数据库的Schema定义在JDO元数据注释文件package.jdo中,位置在src/contrib/hive/metastore/src/model。
计划在未来,元数据存储引擎可以成为一个独立的服务。
如果你想将元数据作为一个网络的服务来在多个节点中访问,请尝试HiveDerbyServerMode。
8、DML操作
将文件中的数据加载到Hive中:
hive> LOAD DATA LOCAL INPATH './examples/files/kv1.txt' OVERWRITE INTO TABLE pokes;
加载到pokes表的文件包含两个用ctrl-a符号分割的数据列,'LOCAL' 意味着文件是从本地文件系统加载,如果没有 'LOCAL' 则意味着从HDFS中加载。
关键词 'OVERWRITE' 意味着当前表中已经存在的数据将会被删除掉。
如果没有给出 'OVERWRITE',则意味着数据文件将追加到当前的数据集中。
注意,通过load命令加载的数据不会被校验正确性。如果文件在HDFS上,他将会被移动到hive所管理的文件系统的命名空间中。Hive目录的根路径是在hive-default.xml文件中的变量hive.metastore.warehouse.dir决定的。
我们建议用户在使用Hive建表之前就创建好这个变量指定的目录。
hive> LOAD DATA LOCAL INPATH './examples/files/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15');
hive> LOAD DATA LOCAL INPATH './examples/files/kv3.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-08');
上面这两个LOAD语句,将加载不同的数据到invites表的分区(partition)中。invites表必须事先使用ds创建好partition。
hive> LOAD DATA INPATH '/user/myname/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15');
上述命令是将HDFS上的文件加载到表中。
注意从HDFS中加载数据,将会把数据移动到目录下。这几乎是瞬间完成的。(注:因为只是在HDFS元数据中修改了文件路径的指向。)
9、SQL 查询
(1)查询示例
下面会演示一些查询范例,在build/dist/examples/queries中可以找到。更多的,可以在hive源码中的ql/src/test/queries/positive中可以找到。
(2)SELECTS和FILTERS
hive> SELECT a.foo FROM invites a WHERE a.ds='2008-08-15';
从invite表的字段 'foo' 中选择所有分区ds=2008-08-15的结果。这些结果并不存储在任何地方,只在控制台中显示。
注意下面的示例中,INSERT (到hive表,本地目录或者HDFS目录) 是可选命令。
hive> INSERT OVERWRITE DIRECTORY '/tmp/hdfs_out' SELECT a.* FROM invites a WHERE a.ds='2008-08-15';
从invites表中选择分区ds=2008-08-15 的所有行,并放入HDFS目录中。结果数据存放于/tmp/hdfs_out目录中的文件(多个文件,文件数量取决于mapper的数量)。
存在分区的表在使用 WHERE 条件过滤的时候必须至少指定一个分区来查询。
hive> INSERT OVERWRITE LOCAL DIRECTORY '/tmp/local_out' SELECT a.* FROM pokes a;
选择pokes表中所有的数据并放到一个本地(注:当前服务器)的文件路径中。
hive> INSERT OVERWRITE TABLE events SELECT a.* FROM profiles a;
hive> INSERT OVERWRITE TABLE events SELECT a.* FROM profiles a WHERE a.key < 100;
hive> INSERT OVERWRITE LOCAL DIRECTORY '/tmp/reg_3' SELECT a.* FROM events a;
hive> INSERT OVERWRITE DIRECTORY '/tmp/reg_4' select a.invites, a.pokes FROM profiles a;
hive> INSERT OVERWRITE DIRECTORY '/tmp/reg_5' SELECT COUNT(*) FROM invites a WHERE a.ds='2008-08-15';
hive> INSERT OVERWRITE DIRECTORY '/tmp/reg_5' SELECT a.foo, a.bar FROM invites a;
hive> INSERT OVERWRITE LOCAL DIRECTORY '/tmp/sum' SELECT SUM(a.pc) FROM pc1 a;
字段计算和,最大值,最小值同样可以使用,注意对不包含HIVE-287的Hive版本,你需要使用COUNT(1) 来代替 COUNT(*)。
(3)GROUP BY
hive> FROM invites a INSERT OVERWRITE TABLE events SELECT a.bar, count(*) WHERE a.foo > 0 GROUP BY a.bar;
hive> INSERT OVERWRITE TABLE events SELECT a.bar, count(*) FROM invites a WHERE a.foo > 0 GROUP BY a.bar;
注意对不包含HIVE-287的Hive版本,你需要使用COUNT(1) 来代替 COUNT(*)。
(4)JOIN
hive> FROM pokes t1 JOIN invites t2 ON (t1.bar = t2.bar) INSERT OVERWRITE TABLE events SELECT t1.bar, t1.foo, t2.foo;
(5)MULTITABLE INSERT(多重插入)
FROM src
INSERT OVERWRITE TABLE dest1 SELECT src.* WHERE src.key < 100
INSERT OVERWRITE TABLE dest2 SELECT src.key, src.value WHERE src.key >= 100 and src.key < 200
INSERT OVERWRITE TABLE dest3 PARTITION(ds='2008-04-08', hr='12') SELECT src.key WHERE src.key >= 200 and src.key < 300
INSERT OVERWRITE LOCAL DIRECTORY '/tmp/dest4.out' SELECT src.value WHERE src.key >= 300;
(6)STREAMING
hive> FROM invites a INSERT OVERWRITE TABLE events SELECT TRANSFORM(a.foo, a.bar) AS (oof, rab) USING '/bin/cat' WHERE a.ds > '2008-08-09';
在map中使用脚本/bin/cat对数据的流式访问(类似于hadoop streaming)。同样的, 流式访问也可以使用在reduce阶段(请查看Hive
Tutorial范例)。
10、简单的使用范例
(1)用户对电影的投票统计
首先,创建一个使用tab分割的文本文件的表
- CREATE TABLE u_data (
- userid INT,
- movieid INT,
- rating INT,
- unixtime STRING)
- ROW FORMAT DELIMITED
- FIELDS TERMINATED BY ' '
- STORED AS TEXTFILE;
wget http://www.grouplens.org/system/files/ml-data.tar+0.gz
tar xvzf ml-data.tar+0.gz
将这个文件加载到刚刚创建的表中:
LOAD DATA LOCAL INPATH 'ml-data/u.data' OVERWRITE INTO TABLE u_data;
计算表u_data中的总行数:
SELECT COUNT(*) FROM u_data;
注意对不包含HIVE-287的Hive版本,你需要使用COUNT(1) 来代替 COUNT(*)。
现在,我们可以在表u_data中做一些复杂的数据分析
创建weekday_mapper.py:
- import sys
- import datetime
- for line in sys.stdin:
- line = line.strip()
- userid, movieid, rating, unixtime = line.split(' ')
- weekday = datetime.datetime.fromtimestamp(float(unixtime)).isoweekday()
- print ' '.join([userid, movieid, rating, str(weekday)])
- CREATE TABLE u_data_new (
- userid INT,
- movieid INT,
- rating INT,
- weekday INT)
- ROW FORMAT DELIMITED
- FIELDS TERMINATED BY ' ';
- add FILE weekday_mapper.py;
- INSERT OVERWRITE TABLE u_data_new
- SELECT
- TRANSFORM (userid, movieid, rating, unixtime)
- USING 'python weekday_mapper.py'
- AS (userid, movieid, rating, weekday)
- FROM u_data;
- SELECT weekday, COUNT(*)
- FROM u_data_new
- GROUP BY weekday;
(2)Apache Web日志数据
Apache日志格式是可以自定义的,作为大多数网管来说都是使用默认设置。
我们可以给默认的Apache日志创建一个如下的表。更多的关于正则序列化/反序列化(!RegexSerDe)可以在这里看到:http://issues.apache.org/jira/browse/HIVE-662
- add jar ../build/contrib/hive_contrib.jar;
- CREATE TABLE apachelog (
- host STRING,
- identity STRING,
- user STRING,
- time STRING,
- request STRING,
- status STRING,
- size STRING,
- referer STRING,
- agent STRING)
- ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
- WITH SERDEPROPERTIES (
- "input.regex" = "([^]*) ([^]*) ([^]*) (-|\[^\]*\]) ([^ "]*|"[^"]*") (-|[0-9]*) (-|[0-9]*)(?: ([^ "]*|".*") ([^ "]*|".*"))?",
- "output.format.string" = "%1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s"
- )
- STORED AS TEXTFILE;
下面整理自Hive Tutorial部分:https://cwiki.apache.org/confluence/display/Hive/Tutorial
(1)Hive是什么?
Hive是基于hadoop构建的数据仓库基础架构,通过提供一系列的工具,使得用户能够方便的做数据ETL,数据结构化,并针对存放在hadoop上的海量数据进行查询和分析。
hive定义了一种简单的类SQL查询语言---QL,QL语言方便熟悉SQL语言的用户去查询数据。此外,hive也支持熟悉map-reduce的开发者使用map-reduce程序对数据做更加复杂的分析。hive可以很好的结合thrift和控制分隔符,也支持用户自定义分隔符。
(2)Hive不是什么?
Hive基于hadoop,hadoop是批处理系统,不能保证低延迟,因此,hive的查询也不能保证低延迟。
Hive的工作模式是提交一个任务,等到任务结束时被通知,而不是实时查询。相对应的是,类似于oracle这样的系统当运行于小数据集的时候,响应非常快,可当处理的数据集非常大的时候,可能需要数小时。需要说明的是,hive即使在很小的数据集上运行,也可能需要数分钟才能完成。
总之,低延迟不是hive追求的首要目标。hive的设计目标是:可伸缩、可扩展、容错及输入格式松耦合。
(3)数据单元
按照数据的粒度大小,hive数据可以被组织成:
1)databases: 避免不同表产生命名冲突的一种命名空间
2)tables:具有相同scema的同质数据的集合
3)partitions:一个表可以有一个或多个决定数据如何存储的partition key
4)buckets(或clusters):在同一个partition中的数据可以根据某个列的hash值分为多个bucket。partition和bucket并非必要,但是它们能大大加快数据的查询速度。
12、数据类型
(1)简单类型:
TINYINT - 1 byte integer
SMALLINT - 2 byte integer
INT - 4 byte integer
BIGINT - 8 byte
BOOLEAN - TRUE/ FALSE
FLOAT - 单精度
DOUBLE - 双精度
STRING - 字符串集合
(2)复杂类型:
Structs: structs内部的数据可以通过DOT(.)来存取,例如,表中一列c的类型为STRUCT{a INT; b INT},我们可以通过c.a来访问域a。
Maps(Key-Value对):访问指定域可以通过['element name']进行,例如,一个Map M包含了一个group->gid的k-v对,gid的值可以通过M['group']来获取。
Arrays:array中的数据为相同类型,例如,假如array A中元素['a','b','c'],则A[1]的值为'b'。
13、内建运算符和函数
包括关系运算符(A=B, A!=B, A<B等等)、算术运算符(A+B, A*B, A&B, A|B等等)、逻辑运算符(A&&B, A|B等等)、复杂类型上的运算符(A[n], M[key], S.x)、各种内建函数。
14、语言能力
hive查询语言提供基本的类sql操作,这些操作基于table和partition,包括:
1. 使用where语句过滤制定行
2. 使用select查找指定列
3. join两张table
4. group by
5. 一个表的查询结果存入另一张表
6. 将一个表的内容存入本地目录
7. 将查询结果存储到hdfs上
8. 管理table和partition(creat、drop、alert)
9. 在查询中嵌入map-reduce程序