2.解压
mkdir -p /home/tuzq/software/hive/
tar -zxvf apache-hive-1.2.1-bin.tar.gz -C /home/tuzq/software/hive/mysql安装可以参考:http://blog.csdn.net/tototuzuoquan/article/details/52711808
mysql安装仅供参考,不同版本mysql有各自的安装流程
rpm -qa | grep mysql(a)配置HIVE_HOME环境变量
vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.8.0_73 export HADOOP_HOME=/home/tuzq/software/hadoop-2.8.0 export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop export HIVE_HOME=/home/tuzq/software/hive/apache-hive-1.2.1-bin export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$HIVE_HOME/bin |
将hadoop集群中的其它的环境变量也配置成这种,如我的hadoop集群是hadoop1,hadoop2,hadoop3,hadoop4,hadoop5。这些我都配置成了上面的同样的环境变量
[root@hadoop1 conf]# cd $HIVE_HOME/conf
[root@hadoop1 conf]# mv hive-env.sh.template hive-env.sh
[root@hadoop1 conf]# vi $HIVE_HOME/conf/hive-env.sh
配置其中的$hadoop_home
(b)配置元数据库信息
在$HIVE_HOME/conf文件加下,创建hive-site.xml文件,文件内容如下:
vi hive-site.xml
添加如下内容:
javax.jdo.option.ConnectionURL
jdbc:mysql://hadoop10:3306/hive?createDatabaseIfNotExist=true
JDBC connect string for a JDBC metastore
javax.jdo.option.ConnectionDriverName
com.mysql.jdbc.Driver
Driver class name for a JDBC metastore
javax.jdo.option.ConnectionUserName
root
username to use against metastore database
javax.jdo.option.ConnectionPassword
root
password to use against metastore database
5.安装hive和mysq完成后,将mysql的连接jar包拷贝到$HIVE_HOME/lib目录下
/home/hadoop/app/hadoop-2.6.4/share/hadoop/yarn/lib/jline-0.9.94.jar
如果是hadoop-2.8.0版本的,发现在/home/tuzq/software/hadoop-2.8.0/share/hadoop/yarn/lib下没有jline-2.12.jar
下面的命令是查看HIVE中的jline的版本号的方式:
[root@hadoop1 lib]# cd $HIVE_HOME/lib
[root@hadoop1 lib]# ls jline-2.12.jar
jline-2.12.jar
[root@hadoop1 lib]#
将创建好的hive远程拷贝到hadoop2,hadoop3,hadoop4,hadoop5服务器上的相同位置
scp -r /home/tuzq/software/hive* root@hadoop2:/home/tuzq/software/
scp -r /home/tuzq/software/hive* root@hadoop3:/home/tuzq/software/
scp -r /home/tuzq/software/hive* root@hadoop4:/home/tuzq/software/
scp -r /home/tuzq/software/hive* root@hadoop5:/home/tuzq/software/
执行完成之后,到mysql中进行查看,发现现象如下:
另外:通过Hive beeline也可以访问hive:
---Beeline要与HiveServer2配合使用,支持嵌入式模式和远程模式
--启动HiverServer2 ,./bin/hiveserver2
命令模式:
hive --service hiveserver2 --hiveconf hive.server2.thrift.port=10001
最后面的port可以更改,hiveserver2默认的端口号是10000。beeline的退出方式:!quit
[root@hadoop1 apache-hive-1.2.1-bin]# bin/beeline
Beeline version 1.2.1 by Apache Hive
beeline> !connect jdbc:hive2://hadoop1:10000
Connecting to jdbc:hive2://hadoop1:10000
Enter username for jdbc:hive2://hadoop1:10000:
Enter password for jdbc:hive2://hadoop1:10000:
Connected to: Apache Hive (version 1.2.1)
Driver: Hive JDBC (version 1.2.1)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://hadoop1:10000> show databases;
+----------------+--+
| database_name |
+----------------+--+
| default |
| mydb |
| userdb |
| userdb2 |
| userdb3 |
+----------------+--+
5 rows selected (0.709 seconds)
0: jdbc:hive2://hadoop1:10000>
查看有哪些表:
[root@hadoop1 apache-hive-1.2.1-bin]# bin/hive
Logging initialized using configuration in jar:file:/home/tuzq/software/hive/apache-hive-1.2.1-bin/lib/hive-common-1.2.1.jar!/hive-log4j.properties
hive> show databases;
OK
default
Time taken: 0.98 seconds, Fetched: 1 row(s)
hive> create database db1; #创建一个数据库
OK
Time taken: 0.239 seconds
hive> show databases; #显示所有的数据库
OK
db1
default
Time taken: 0.015 seconds, Fetched: 2 row(s)
hive>
然后进入hdfs上进行查看http://hadoop1:50070/ :
6.建表(默认是内部表)
use db1;
hive> create table trade_detail(id bigint,account string,income double,expense double,time string) row format delimited fields terminated by '\t';
进入hdfs进行查看:
select nation, avg(size) from beauties group by nation order by avg(size);
注意:如果在此过程中获取的结果是NULL的,说明创建表的时候需要加上:lines terminated by '\n'
如果想通过drop table if exists table_name删除表时删除不了,请换$HIVE_HOME/lib中的mysql-connector-java。比如我使用的是:mysql-5.7.15-linux-glibc2.5-x86_64.tar.gz,开始的时候使用的是mysql-connector-java-5.1.7.jar,最后换成mysql-connector-java-5.1.38.jar,发现就可以drop表了。
查看database,删除数据库
以下是使用CASCADE查询删除数据库。这意味着要全部删除相应的表在删除数据库之前:
hive> show databases;
OK
default
mydb
userdb
userdb2
userdb3
Time taken: 0.962 seconds, Fetched: 5 row(s)
hive> drop database IF EXISTS userdb3 CASCADE;
OK
Time taken: 0.203 seconds
hive> show databases;
OK
default
mydb
userdb
userdb2
Time taken: 0.014 seconds, Fetched: 4 row(s)
hive>
修改表
Alter Table语句,它是在Hive中用来修改表的
语法:
ALTER TABLE name RENAME TO new_name ALTER TABLE name ADD COLUMNS (col_spec[, col_spec ...]) ALTER TABLE name DROP [COLUMN] column_name ALTER TABLE name CHANGE column_name new_name new_type ALTER TABLE name REPLACE COLUMNS (col_spec[, col_spec ...])
hive> show tables;
OK
testhivedrivertable
Time taken: 0.029 seconds, Fetched: 1 row(s)
hive> ALTER TABLE testhivedrivertable RENAME To testHive;
OK
Time taken: 0.345 seconds
hive> show tables;
OK
testhive
Time taken: 0.031 seconds, Fetched: 1 row(s)
修改列中列的类型:
hive> desc testhive;
OK
key int
value string
Time taken: 0.161 seconds, Fetched: 2 row(s)
hive> ALTER TABLE testhive CHANGE value value Double;
OK
Time taken: 0.251 seconds
hive> desc testhive;
OK
key int
value double
Time taken: 0.126 seconds, Fetched: 2 row(s)
hive>
为表添加一列:
hive> ALTER TABLE testhive ADD COLUMNS (
> dept STRING COMMENT 'Departname name');
OK
Time taken: 0.219 seconds
hive> desc testhive;
OK
key int
value double
dept string Departname name
Time taken: 0.09 seconds, Fetched: 3 row(s)
hive>
删除表
删除表的语法是:
hive>DROP TABLE IF EXISTS testhive;
创建分区
Hive组织表到分区。它是将一个表到基于分区列,如日期,城市和部门的值相关方式。使用分区,很容易对数据进行部分查询。很容易对数据进行部分查询。
表或分区是细分成桶,以提供额外的结构,可以使用更搞笑的查询的数据。桶的工作是基于表的一些列的散列函数值。
添加分区,语法是:
ALTER TABLE table_name ADD [IF NOT EXISTS] PARTITION partition_spec
[LOCATION 'location1'] partition_spec [LOCATION 'location2'] ...;
partition_spec:
:(p_column = p_col_value, p_column = p_col_value, ...)
先做准备工作,创建表:
CREATE TABLE IF NOT EXISTS employee (eid int, name String,
destination String)
partitioned by (salary String)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
hive>desc employee;
经过上面步骤,表已经添加了一个分区
导入数据:
[root@hadoop1 hivedata]# cat /home/tuzq/software/hivedata/sample.txt
1201 pal 45000 Technical manager
1202 Manisha 45000 Proof reader
[root@hadoop1 hivedata]#
将上面的数据导入到分区:
LOAD DATA LOCAL INPATH '/home/tuzq/software/hivedata/sample.txt' INTO TABLE employee PARTITION(salary = '45000');
注意上满的红字,表示将数据到如45000这个分区中。
在hdfs上的效果如下:
http://hadoop1:50070/explorer.html#/user/hive/warehouse/userdb.db/employee
下面再次给表添加另外一个分区值:
ALTER TABLE employee ADD PARTITION (salary ='40000') location '/40000/part40000';
添加location之后,它在HDFS上的位置将会改变,将会到/40000/part40000中。效果图如下:
http://hadoop1:50070/explorer.html#/40000/part40000
创建2个分区的方式:
双分区建表语句:create table table_name (id int, content string) partitioned by (dt string, hour string);双分区表,按天和小时分区,在表结构中新增加了dt和hour两列。
先以dt为文件夹,再以hour子文件夹区分
查看分区语句:
hive> show partitions employee;
OK
salary=40000
salary=45000
Time taken: 0.088 seconds, Fetched: 2 row(s)
hive>
再如:
建分区表
hive> create table td_part(id bigint,account string,income double,expenses double,time string) partitioned by (logdate string)row format delimited fields terminated by '\t';
OK
Time taken: 0.114 seconds
hive> show tables;
OK
td_part
trade_detail
Time taken: 0.021 seconds, Fetched: 2 row(s)
hive>
创建视图和索引
视图在Hive的用法和SQL视图用法相同。它是一个标准的RDBMS概念。我们可以在视图上执行DML操作。
创建视图的语法如下:
CREATE VIEW [IF NOT EXISTS] view_name [(column_name [COMMENT column_comment], ...) ]
[COMMENT table_comment]
AS SELECT ...
hive> desc employee;
OK
eid int
name string
destination string
salary string
# Partition Information
# col_name data_type comment
salary string
Time taken: 0.08 seconds, Fetched: 9 row(s)
hive> create VIEW emp_45000 AS
> SELECT * FROM employee
> WHERE salary = 45000;
删除一个视图的方式:
hive > DROP VIEW emp_45000;
创建索引:
创建索引的语法如下:
CREATE INDEX index_name
ON TABLE base_table_name (col_name, ...)
AS 'index.handler.class.name'
[WITH DEFERRED REBUILD]
[IDXPROPERTIES (property_name=property_value, ...)]
[IN TABLE index_table_name]
[PARTITIONED BY (col_name, ...)]
[
[ ROW FORMAT ...] STORED AS ...
| STORED BY ...
]
[LOCATION hdfs_path]
[TBLPROPERTIES (...)]
HIVE的四种数据导入方式:
HIVE的几种常见的数据导入方式,这里介绍四种:
(1)、从本地文件系统中导入数据到Hive表;
(2)、从HDFS上导入数据到Hive表
(3)、从别的表中查询出相应的数据并导入到Hive表中。
(4)、在创建表的时候通过从别的表中查询出相应的记录并插入到所创建的表中。
一、从本地文件系统中导入数据到Hive表
先在Hive里面创建好表,如下:
hive> create table wyp(id int,name string,age int,tel string) ROW FORMAT DELIMITED FIELDS TERMINATED BY ' ' lines terminated by '\n' STORED AS TEXTFILE;
注意上面的:ROW FORMAT DELIMITED FIELDS TERMINATED BY ' ' 注意这个分割的字符,若是设置的不好,最后能够插入数据库,但是select出来的结果是NULL.
wyp.txt文件中的数据列之间使用空格分割的,可以通过下面的语句将这个文件里面的数据导入到wyp表里面,操作如下:
hive> load data local inpath '/home/tuzq/software/hive/apache-hive-1.2.1-bin/wyp.txt' into table wyp;
Loading data to table default.wyp
Table default.wyp stats: [numFiles=1, totalSize=67]
OK
Time taken: 0.35 seconds
hive> select * from wyp;
OK
1 wyp 25 13188888888888
2 test 30 13888888888888
3 zs 34 899314121
Time taken: 0.086 seconds, Fetched: 3 row(s)
hive>
这样就将wyp.txt里面的内容导入到wyp表里面去了,可以到wyp表的数据目录下查看,http://hadoop1:50070/explorer.html#/user/hive/warehouse/db1.db: 二、HDFS上导入数据到hive表
从本地文件系统中将数据导入到Hive表的过程中,其实是先将数据临时复制到HDFS的一个目录下(典型的情况是复制到上传用户的HDFS的目录下,比如/根目录下),然后在将数据从那个临时目录下移动(注意,这里说的是移动,不是复制)到对应的数据目录里面。既然如此,那么Hive肯定支持将数据直接从HDFS上的一个目录移动到相应Hive表的数据目录下,假设有这个文件/add.txt,具体的操作如下:
[root@hadoop1 apache-hive-1.2.1-bin]# ls
add.txt bin book.txt conf examples hcatalog lib LICENSE NOTICE README.txt RELEASE_NOTES.txt scripts wyp.txt
[root@hadoop1 apache-hive-1.2.1-bin]# vim add.txt
[root@hadoop1 apache-hive-1.2.1-bin]# hdfs dfs -put add.txt /
[root@hadoop1 apache-hive-1.2.1-bin]# hdfs dfs -ls /
Found 4 items-rw-r--r-- 3 root supergroup 67 2017-06-11 11:34 /add.txt
-rw-r--r-- 3 root supergroup 3719 2017-06-10 12:11 /kms.sh
drwx-wx-wx - root supergroup 0 2017-06-10 22:06 /tmp
drwxr-xr-x - root supergroup 0 2017-06-10 22:27 /user
[root@hadoop1 apache-hive-1.2.1-bin]# hdfs dfs -cat /add.txt
4 wyp
25 131888888888885 test 30 138888888888886 zs 34 899314121
[root@hadoop1 apache-hive-1.2.1-bin]#
上面是需要插入数据的内容,这个文件时存放在HDFS上/add.txt里面的(和一中提到的不同,一中提到的文件是存放在本地文件系统上,并且在load数据的时候加上了关键字local),我们可以同通过下面的命令将这个文件里面的内容导入到Hive表中,具体操作如下:
hive> select * from wyp;
OK1 wyp
25 131888888888882 test 30 138888888888883 zs 34 899314121
Time taken: 0.086 seconds, Fetched: 3 row(s)
hive> load data inpath '/add.txt' into table wyp;
Loading data to table default.wypTable default.wyp stats: [numFiles=2, totalSize=134]OKTime taken: 0.283 seconds
hive> select * from wyp;
OK4 wyp
25 131888888888885 test
30 138888888888886 zs
34 8993141211 wyp
25 131888888888882 test
30 138888888888883 zs
34 899314121
Time taken: 0.076 seconds, Fetched: 6 row(s)
hive>
从上面的执行结果我们可以看到,数据的确导入到wyp表中了!请注意 load data inpath '/add.txt' into table wyp; 里面没有local这个单词,这个是和一中的区别。
三、从别的表中查询出相应的数据并导入到Hive表中
假设Hive中有test表,其建表语句如下所示:
- hive> create table test(
- > id int, name string
- > ,tel string)
- > partitioned by
- > (age int)
- > ROW FORMAT DELIMITED
- > FIELDS TERMINATED BY '\t'
- > STORED AS TEXTFILE;
- OK
- Time taken: 0.261 seconds
复制代码
大体和wyp表的建表语句类似,只不过test表里面用age作为了分区字段。对于分区,这里在做解释一下:
分区:在Hive中,表的每一个分区对应表下的相应目录,所有分区的数据都是存储在对应的目录中。比如wyp表有dt和city两个分区,则对应dt=20131218,city=BJ对应表的目录为/user/hive/warehouse/dt=20131218/city=BJ,所有属于这个分区的数据都存放在这个目录中。
下面语句就是将wyp表中的查询结果并插入到test表中:
- hive> insert into table test
- > partition (age='25')
- > select id, name, tel
- > from wyp;
- #####################################################################
- 这里输出了一堆Mapreduce任务信息,这里省略
- #####################################################################
- Total MapReduce CPU Time Spent: 1 seconds 310 msec
- OK
- Time taken: 19.125 seconds
- hive> select * from test;
- OK
- 5 wyp1 131212121212 25
- 6 wyp2 134535353535 25
- 7 wyp3 132453535353 25
- 8 wyp4 154243434355 25
- 1 wyp 13188888888888 25
- 2 test 13888888888888 25
- 3 zs 899314121 25
- Time taken: 0.126 seconds, Fetched: 7 row(s)
复制代码
这里做一下说明:
我们知道我们传统数据块的形式insert into table values(字段1,字段2),这种形式hive是不支持的。
通过上面的输出,我们可以看到从wyp表中查询出来的东西已经成功插入到test表中去了!如果目标表(test)中不存在分区字段,可以去掉partition (age=’25′)语句。当然,我们也可以在select语句里面通过使用分区值来动态指明分区:
- hive> set hive.exec.dynamic.partition.mode=nonstrict;
- hive> insert into table test
- > partition (age)
- > select id, name,
- > tel, age
- > from wyp;
- #####################################################################
- 这里输出了一堆Mapreduce任务信息,这里省略
- #####################################################################
- Total MapReduce CPU Time Spent: 1 seconds 510 msec
- OK
- Time taken: 17.712 seconds
- hive> select * from test;
- OK
- 5 wyp1 131212121212 23
- 6 wyp2 134535353535 24
- 7 wyp3 132453535353 25
- 1 wyp 13188888888888 25
- 8 wyp4 154243434355 26
- 2 test 13888888888888 30
- 3 zs 899314121 34
- Time taken: 0.399 seconds, Fetched: 7 row(s)
复制代码
这种方法叫做动态分区插入,但是Hive中默认是关闭的,所以在使用前需要先把hive.exec.dynamic.partition.mode设置为nonstrict。当然,Hive也支持insert overwrite方式来插入数据,从字面我们就可以看出,overwrite是覆盖的意思,是的,执行完这条语句的时候,相应数据目录下的数据将会被覆盖!而insert into则不会,注意两者之间的区别。例子如下:
- hive> insert overwrite table test
- > PARTITION (age)
- > select id, name, tel, age
- > from wyp;
复制代码
更可喜的是,Hive还支持多表插入,什么意思呢?在Hive中,我们可以把insert语句倒过来,把from放在最前面,它的执行效果和放在后面是一样的,如下:
- hive> show create table test3;
- OK
- CREATE TABLE test3(
- id int,
- name string)
- Time taken: 0.277 seconds, Fetched: 18 row(s)
- hive> from wyp
- > insert into table test
- > partition(age)
- > select id, name, tel, age
- > insert into table test3
- > select id, name
- > where age>25;
- hive> select * from test3;
- OK
- 8 wyp4
- 2 test
- 3 zs
- Time taken: 4.308 seconds, Fetched: 3 row(s)
复制代码
可以在同一个查询中使用多个insert子句,这样的好处是我们只需要扫描一遍源表就可以生成多个不相交的输出。这个很酷吧! 四、在创建表的时候通过从别的表中查询出相应的记录并插入到所创建的表中
在实际情况中,表的输出结果可能太多,不适于显示在控制台上,这时候,将Hive的查询输出结果直接存在一个新的表中是非常方便的,我们称这种情况为CTAS(create table .. as select)如下:
- hive> create table test4
- > as
- > select id, name, tel
- > from wyp;
- hive> select * from test4;
- OK
- 5 wyp1 131212121212
- 6 wyp2 134535353535
- 7 wyp3 132453535353
- 8 wyp4 154243434355
- 1 wyp 13188888888888
- 2 test 13888888888888
- 3 zs 899314121
- Time taken: 0.089 seconds, Fetched: 7 row(s)
复制代码
数据就插入到test4表中去了,CTAS操作是原子的,因此如果select查询由于某种原因而失败,新表是不会创建的!
Java远程调用hive
使用java远程连接hive,在这个过程中需要先启动:hiveServer2. (注意:org.apache.hive.jdbc.HiveDriver依赖的jar包是:hive-jdbc-1.2.1.jar)
package hive;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class HiveCreateDb {
/*
* hiverserver 版本使用此驱动 private static String driverName =
* "org.apache.hadoop.hive.jdbc.HiveDriver";
*/
/*
* hiverserver2 版本使用此驱动
*/
private static String driverName = "org.apache.hive.jdbc.HiveDriver";
public static void main(String[] args) throws Exception {
Class.forName(driverName);
/* hiverserver 版本jdbc url格式,主要体现在jdbc:hive:// */
// Connection con =
// DriverManager.getConnection("jdbc:hive://hadoop1:10000/default", "",
// "");
/* hiverserver2 版本jdbc url格式,主要体现在jdbc:hive2:// */
Connection con = DriverManager.getConnection("jdbc:hive2://hadoop1:10000/default", "", "");
Statement stmt = con.createStatement();
// 下面的这一句如果在没有userdb数据库的情况下,可以放开。
// stmt.executeQuery("CREATE DATABASE userdb");
// 参数设置测试
// boolean resHivePropertyTest = stmt
// .execute("SET tez.runtime.io.sort.mb = 128");
boolean resHivePropertyTest = stmt.execute("set hive.execution.engine=tez");
System.out.println(resHivePropertyTest);
stmt.execute("USE userdb");
String tableName = "testHiveDriverTable";
try {
stmt.executeQuery("drop table " + tableName);
} catch (Exception e) {
e.printStackTrace();
}
ResultSet res;
try {
res = stmt.executeQuery("create table " + tableName + " (key int, value string)");
} catch (Exception e) {
e.printStackTrace();
}
// show tables
String sql = "show tables '" + tableName + "'";
System.out.println("Running: " + sql);
res = stmt.executeQuery(sql);
if (res.next()) {
System.out.println(res.getString(1));
}
// //describe table
sql = "describe " + tableName;
System.out.println("Running: " + sql);
res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(res.getString(1) + "\t" + res.getString(2));
}
// load data into table
// NOTE: filepath has to be local to the hive server
// NOTE: /tmp/a.txt is a ctrl-A separated file with two fields per
// line
String filepath = "/tmp/a.txt";
sql = "load data local inpath '" + filepath + "' into table " + tableName;
System.out.println("Running: " + sql);
res = stmt.executeQuery(sql);
// select * query
sql = "select * from " + tableName;
System.out.println("Running: " + sql);
res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(String.valueOf(res.getInt(1)) + "\t" + res.getString(2));
}
// regular hive query
sql = "select count(1) from " + tableName;
System.out.println("Running: " + sql);
res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(res.getString(1));
}
stmt.close();
con.close();
}
}