hive 集群搭建与表的简单操作

Hive 是基于 hadoop 的一个数据仓库,将结构化的数据文件存储在 hdfs 上,数据的结构信息存储在关系型数据库中(如mysql, oracle, derby),可以将sql语句转化为 mapreduce 任务,mapreduce 任务需要编程人员使用 java 语言写 MapTask, ReduceTask 的逻辑代码,打包成 jar 上传到 hdfs 中,而 hive 的 sql 语句进行统计分析则省去了MR的编码打包的过程,十分适合做统计分析。

Hive 构建在 Hadoop 集群之上,查询等(除 查询外)操作通过 MR 的作业执行,所以在 Hive 搭建前,集群上要*已经部署 hadoop (hdfs, yarn 环境)

在搭建好的 hadoop 集群上部署 Hive

这里我也在上一篇的四台虚拟机上搭建 Hive,Hive 的部署分单用户模式和多用户模式,单用户模式是Hive服务和客户端在一台结点上启动,多用户模式是客户端和服务端在两台结点上,下面部署 Hive 的多用户模式,角色分配如下

结点 角色
master mysql
slave1 Hive Server
slave2 Hive Client
  1. 安装 mysql,开启外部访问授权,重启 mysql 服务或刷新授权表
  2. 上传 Hive 的压缩文件,解压,将 hive/bin 路径添加到环境变量中
  3. 将 mysql-connector-java-*.jar 拷贝到 hive/lib 路径下
  4. 在服务端 (slave1) 和客户端 (slave2) 中,将 hive/conf 下的 hive-default.xml.template 重命名为 hive-site.xml
  5. 服务端 hive/conf/hive-site.xml 中内的配置项改为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- hdfs 路径 -->
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/usr/hive/warehouse</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://master:3306/hive?createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<!-- mysql 登陆名密码 -->
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>root</value>
</property>

上面配置项中hive.metastore.warehouse.dir的值为 Hive 数据仓库的数据在 hdfs 中的存储路径,当创建一个表,如 school 表,会在配置的路径下创建一个名为 school 的路径,如/usr/hive/warehouse/school,向school 表中添加的数据会存放在这个路径下

  1. 客户端 hive/conf/hive-site.xml 中内的配置项改为:
1
2
3
4
5
<!-- 服务端地址 -->
<property>
<name>hive.metastore.uris</name>
<value>thrift://slave1:9083</value>
</property>
  1. 启动 Hive 服务端进程:hive --service metastore
  2. 启动 Hive 客户端进程:hive,即可进入 hive 数据仓库进行操作

数据类型

操作指令

hive 的很多指令与关系型数据库的 sql 语句类似

创建表

Hive 的表分为内部表和外部表

内部表

直接创建表,创建后再向表中导入数据。创建语句:指定表列名,类型,列之间 (FIELDS) 的分隔符,特殊类型: array (COLLECTION ITEMS), map (MAP KEYS) 中元素之间的分隔符(不能是分号 “;”)

1
2
3
4
5
6
create table student
(id int, name string, interests array<string>, score map<string, float>)
row format delimited
FIELDS TERMINATED BY ' '
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':';

执行完建表语句,可以看到 hdfs 文件系统中的 hive 存储路径下多了 student文件夹,里面是空的,导入的数据则存放在 student

外部表

先有数据,根据数据的格式建立数据表,可以理解建立表与 hdfs 一个路径下数据的映射

加入external关键字和要对应的 hdfs 路径,该路径下所有文件中的数据都是表中的数据:

1
2
3
4
5
6
7
create external table student_external
(id int, name string, interests array<string>, score map<string, float>)
row format delimited
FIELDS TERMINATED BY ' '
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':'
location '/usr/zjm/external/'

注:示例中 location 后的路径是 hdfs 路径,会将 /usr/zjm/external下的所有文件中的数据都作为student_external表的数据,格式不一致各字段显示 null

内部表和外部表的区别

  1. 外部表是已有数据,根据数据设计表,去对应hdfs的一个路径,外部表更常用
  2. 内部表创建之初没有数据,会在hdfs中建立以表名命名的文件夹(如果没有该文件夹的话)
  3. 删除内部表时会把文件夹以及内部文件数据一同删掉,外部表只删除表的元数据,不会删除对应的路径

向表中添加数据

使用 insert into table values(v1,v2,...); 的方式会通过 MR 任务的形式很慢,要通过文件上传的形式将数据导入到表中,文件中数据格式如下:

1
2
3
4
0 zjm0 football,basketball,music math:91.44,chinese:76.97,english:98.75
1 zjm1 football,tennis,music math:97.96,chinese:80.22,english:89.79
2 zjm2 basketball,pingpang,swim,music math:95.62,chinese:76.54,english:90.73
...

导入语句:load data local inpath '/usr/local/data.txt' into table student;,其中 inpath后的路径是本地路径,将一个本地文件上传到 hdfs 中做为表的数据,导入后在 hdfs 中可以看到 /usr/hive/warehouse/student下多了data.txt

注:表中的数据就是对应目录下的所有文件中的数据,所以 load 就是执行 hdfs dfs -put 将文件上传到对应hdfs目录中

student

查询表

当查询表内容时:select * from student,先从关系型数据库中读到表结构,再从表对应的 hdfs 路径下读到所有文件中的数据低按照表结构封装,如果不符合表结构则显示一条记录的各个字段都显示 null

分区表

对一个表的内容按某个字段分成不同区域,方便查询

1
2
3
4
5
6
7
create table student_p
(id int, name string, interests array<string>, score map<string, float>)
partitioned by (grade int)
row format delimited
FIELDS TERMINATED BY ' '
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':';

上面建立了按照年级的学生分区表,当插入数据时可以将不同年级的学生的数据分别放入不同的分区中,在hdfs中一个分区是表文件夹下的一个文件夹

导入数据:load data local inpath '/.../data.txt' into table student_p partition (grade=3),这里的data.txt中不能含有 grade 字段,且里面的数据都应该属于相同 grade 的 student 信息,查询的时候是根据 hdfs 的文件夹名grade=3添加字段

student_p

多分区:指定多个分区,出现多级目录

partitioned by (grade int, tall int, sex string)

load data local inpath '/.../data.txt' into table student_p partition (grade=3, tall=170, sex='girl')

student_p3

也可以先在 hdfs 上建立好分区目录,用msck repair table ...同步分区信息

导入其他表的数据

1
2
3
4
5
from s1
insert overwrite table s2
select id,name,sex;
insert into table s3;
select id,tall,weight;
您的支持鼓励我继续创作!