简介
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能。
为什么要使用Hive?
首先我们看下直接使用Hadoop所面临的问题:
- 人员学习成本高
- 项目周期要求太短
- MapReduce实现复杂查询逻辑开发难度太大
由于Hadoop存在上述问题,所有引入Hive:
- 操作接口采用类SQL语法,提供快速开发的能力
- 避免去写MapReduce程序,减少开发人员的学习成本
- 扩展功能很方便
Hive的特点
- 可扩展:Hive可以自由的扩展集群的规模,一般情况下不需要重启服务。
- 延展性:Hive支持用户自定义函数,用户可以根据自己需求实现自己的函数。
- 容错:良好的容错性,节点出问题SQL仍可完成执行。
Hive架构和原理
原理:Hive通过用户提供的以下系列交互接口,接受到用户的指令(SQL),使用自己的Driver,结合元数据(MetaStore),将这些指令翻译成MapReduce,提交到Hadoop中执行,最后,将执行的结果输出到用户交互接口。
Hive的服务端组件
- 用户接口:Client CLI(hive shell命令行),JDBC/ODBC(访问hive),WEBUI(浏览器访问hive)
- 元数据:MetaStore,包括,表名,表所属数据库(默认default),表的拥有者,列/区分字段,表的类型(是否是外部表),表的数据所在目录等。
- Hadoop使用HDFS进行存储,使用MapReduce进行计算。
-
驱动器:Driver
(1) 解析器(SQL Parser):将SQL字符转换成抽象的语法树AST,这一步一般使用都是第三方工具库完成,比如antlr,对AST进行语法分析,比如表是否存在,字段是否存在,SQL语句是否有误
(2)编译器(Physical Plan):将AST编译生成逻辑执行计划
(3)优化器(Query Optimizer):对逻辑执行计划进行优化
(4)执行器(Execution):把逻辑执行计划转换成可以运行的物理计划,对于Hive来说,就是MR/Spark
Hive与传统数据库对比
总结:Hive具有sql数据库的外表,但应用场景完全不同,Hive只适合用来做批量数据统计分析
Hive的数据存储
- Hive中所有的数据都存储在 HDFS 中,没有专门的数据存储格式(可支持Text,SequenceFile,ParquetFile,Rcfile等)。
- 只需要在创建表的时候告诉 Hive 数据中的列分隔符和行分隔符,Hive 就可以解析数据。
- Hive 中包括以下数据模型:DB、Table、External Table、Partition、Bucket。
- DB: 在 HDFS 中表现为 ${hive.metastore.warehouse.dir} 目录下的一个文件夹
- Table: 在HDFS中表现为所述DB目录下的一个文件夹
- External Table:与Table类似,不过期数据存放位置可以在任意指定路径
- Partition: 在HDFS中表现为Table目录下的子目录
- Bucket: 在HDFS中表现为表目录下根据 hash 散列之后的多个文件
Hive的安装部署
- 单机版
-
元数据库MySQL版
Hive使用方式
-
1. Hive交互shell
bin/hive
hive> select * from t_user; -
2. 将Hive启动为一个服务:
启动方式:
(1)启动为前台:bin/hiveserver2
(2)启动为后台:nohup bin/hiveserver2 1>/var/log/hiveserver.log 2>/var/log/hiveserver.err &
启动成功后,可以在别的节点上使用beeline去连接
方式1:hive/bin/beeline 回车,进入beeline的命令界面
输入命令连接hiveserver2
beeline> !connect jdbc:hive2://hdp-05:10000
(hdp-05是hiveserver2所启动的那台主机名,端口默认:10000)方式2 : 启动就连接
bin/beeline -u jdbc:hive2://hdp-05:10000 -n hadoop
接下来就可以做正常sql查询了 3. 将Hive作为命令一次性运行
bin/hive -e ‘sql’
bin/hive -e "sql1;sql2;sql3;sql4"
事先将sql语句写入一个文件比如 q.hql ,然后用hive命令执行:
bin/hive -f q.hql
4. 脚本化运行
可以将方式3写入一个xxx.sh脚本中
vi t_test_hive.sh
#!/bin/bash
hive -e "select * from db_test.t_user"
hive -e "select * from default.t_user"
hql = "create table default.t_bash as select * from db_test.t_user"
hive -e "$hql"
Hive 基本操作
DDL操作
- 创建库
create database db1;
hive就会在 /user/hive/warehouse/下新建一文件夹
- 创建内部表
use db1;
create table t_test(id int,name string,age int,create_time bigint) row format delimited terminated by '\001';
建表后,hive会在仓库目录中建一个表目录:`
/user/hive/warehouse/db1.db/t_test`
- 创建外部表
create external table t_test1(id int,name string,age int,create_time bigint)
row format delimited
fields terminated by '\001'
location '/external/t_test';
-
内部表&外部表
未被external修饰的是内部表(managed table),被external修饰的为外部表(external table);
**区别: **- 内部表数据由Hive自身管理,外部表数据由HDFS管理;
- 内部表数据存储的位置是hive.metastore.warehouse.dir(默认:/user/hive/warehouse),外部表数据的存储位置由自己制定;
- 删除内部表会直接删除元数据(metadata)及存储数据;删除外部表仅仅会删除元数据,HDFS上的文件并不会被删除;
- 对内部表的修改会将修改直接同步给元数据,而对外部表的表结构和分区进行修改,则需要修复(MSCK REPAIR TABLE table_name;)
-
导入数据
本质就是把数据文件放入表目录,可以用hive命令来做:- 从本地导入
load data local inpath 'file_path' into table tbname;
- 从hdfs上导入数据
load data inpath ‘hafd_file_path’ into table tbname;
应用场景:使用与大数据的存储
- load方式的覆盖
load data local inpath 'file_path' overwrite into table tbname;
应用场景:用于临时表。
- 子查询方式
应用场景:对于数据查询的结构的保存。
table tb2 as select * from tb1;
- insert into
应用场景:和上面的应用场景相同,因为后面接的都是select查询。
不需要as,直接后接入select。
insert into table tb2 select q1;
-
location
这种情况适用于前面说的外部表,或者管理表中对于表数据的指定。
然后put就好。
我想,前提是需要先建一个表。
在HDFS上看效果
-
建分区表
分区的意义在于将数据分散到子目录存储,以便于查询时让数据读取范围更精准。create table t_test1(id int,name string,age int,create_time bigint) partitioned by (day string,country string) row format delimited fields terminated by '\001';
插入数据到指定分区:
hive> load data [local] inpath '/data/path1' [overwrite] into table t_test1 partition(day='2019-10-14',country='China'); hive> load data [local] inpath '/data/path2' [overwrite] into table t_test1 partition(day='2019-10-15',country='China'); hive> load data [local] inpath '/data/path3' [overwrite] into table t_test1 partition(day='2019-10-16',country='England');
导入完成后,形成的目录结构如下:
/user/hive/warehouse/db1.db/t_test1/day=2019-10-14/country=China/... /user/hive/warehouse/db1.db/t_test1/day=2019-10-15/country=England/... /user/hive/warehouse/db1.db/t_test1/day=2019-10-16/country=China/...
注意:分区中的字段不能是表中已存在字段
查询 2019-10-15 数据:
select from t_test1 where day='2019-10-15'
这样MapReduce程序就只会去查 day='2019-10-15' 子目录的文件数据。
表定义的修改:改表名、增加列,删除列,修改列定义.......
DML操作
基本查询语法跟标准sql基本一致
FROM T1
JOIN T2
WHERE CONDITION
GROUP BY FILEDS
HAVING CONDTION
ORDER BY FIELDS DESC|ASC
各类JOIN语法跟SQL也基本一致,不过HIVE有一个自己的特别的JOIN: LEFT SEMI JOIN
hive在1.2.0之前不支持“不等值”join,但在1.2.0后支持不等值join,只是语法必须按如下形式写:
SELECT A.*,B.* from A,B WHERE A.ID>B.ID;
各类流程控制语句根SQL也基本一致:
case when l.userid is null
then concat('hive',rand())
when l.userid > 20
then concat('hive',rand())
else l.userid