Hive的定义
hive是一个建立在Hadoop上的开源数据仓库软件,可以将结构化的数据文件映射为一张数据库表,基于表提供了一种类似SQL的查询模型,称为hive查询语言(HQL),用于访问和分析存储在Hadoop文件中的大型数据集,十分适合数据仓库的统计分析。
Hive的本质
hive核心是将HQL转换为MapReduce程序,然后将程序提交到Hadoop群集执行。Hive由Facebook实现并开源。
从功能上来说,数据仓库软件,至少需要具备两种能力:存储数据的能力、分析数据的能力。hive是借助Hadoop,利用Hadoop的HDFS存储数据,利用 MapReduce查询分析数据。Hive最大的魅力在于用户只需要专注于编写HQL,Hive帮用户转换为MapReduce程序完成对数据的分析。用户编写HQL语句,Hive自动将SQL转换为MapReduce程序,处理位于HDFS上的结构化数据。Hive软件本身承担的是SQL语法解析编译称为MapReduce的功能职责。
Hive的本质简单理解
Hive处理的数据存储在HDFS上
Hive分析数据底层的实现是MapReduce
执行程序运行在Yarn上
为什么要使用Hive?
使用Hadoop MapReduce直接处理所面临的问题:学习成本太高,需要掌握JAVA语言;MapReduce实现复杂查询逻辑开发难度太大。Hive处理数据的好处:操作结构采用类似SQL语法,提供快速开发的能力,简单容易上手
Hive与关系数据库的区别
使用hive的命令行接口,感觉很像操作关系数据库,但是hive和关系数据库还是有很大的不同,hive与关系数据库的区别具体如下:
hive和关系数据库存储文件的系统不同,hive使用的是hadoop的HDFS(hadoop的分布式文件系统),关系数据库则是服务器本地的文件系统;
hive使用的计算模型是mapreduce,而关系数据库则是自己设计的计算模型;
关系数据库都是为实时查询的业务进行设计的,而hive则是为海量数据做数据挖掘设计的,实时性很差;实时性的区别导致hive的应用场景和关系数据库有很大的不同;
Hive很容易扩展自己的存储能力和计算能力,这个是继承hadoop的,而关系数据库在这个方面要比数据库差很多。
关系数据库里,表的加载模式是在数据加载时候强制确定的(表的加载模式是指数据库存储数据的文件格式),如果加载数据时候发现加载的数据不符合模式,关系数据库则会拒绝加载数据,这个就叫“写时模式”,写时模式会在数据加载时候对数据模式进行检查校验的操作。Hive在加载数据时候和关系数据库不同,hive在加载数据时候不会对数据进行检查,也不会更改被加载的数据文件,而检查数据格式的操作是在查询操作时候执行,这种模式叫“读时模式”。在实际应用中,写时模式在加载数据时候会对列进行索引,对数据进行压缩,因此加载数据的速度很慢,但是当数据加载好了,我们去查询数据的时候,速度很快。但是当我们的数据是非结构化,存储模式也是未知时候,关系数据操作这种场景就麻烦多了,这时候hive就会发挥它的优势。
关系数据库一个重要的特点是可以对某一行或某些行的数据进行更新、删除操作,hive不支持对某个具体行的操作,hive对数据的操作只支持覆盖原数据和追加数据。Hive也不支持事务和索引。更新、事务和索引都是关系数据库的特征,这些hive都不支持,也不打算支持,原因是hive的设计是海量数据进行处理,全数据的扫描时常态,针对某些具体数据进行操作的效率是很差的,对于更新操作,hive是通过查询将原表的数据进行转化最后存储在新表里,这和传统数据库的更新操作有很大不同。
Hive的优缺点
优点
类似于SQL语句,简单学习易上手
避免了去写 MapReduce,减少开发人员的学习成本
Hive 的执行延迟比较高,因此 Hive 常用于数据分析,对实时性要求不高的场合
Hive 优势在于处理大数据,对于处理小数据没有优势,因为 Hive 的执行延迟比较高
Hive 支持用户自定义函数,用户可以根据自己的需求来实现自己的函数
缺点
Hive 的 HQL 表达能力有限
Hive 的效率比较低
Hive本质是一个MR
Hive数据存储
Hive数据可区分为表数据和元数据,表数据我们都知道是表中的数据,而元数据是用来存储表名、表所属的数据库(默认是 default)、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录
Hive是基于Hadoop分布式文件存储的,它的数据存储在HDFS中。Hive中常见的数据导入方式
本地文件系统中导入数据到Hive
从HDFS上导入数据到Hive表
从其他表中查询出相应的数据并导入Hive表中
在创建表的时候通过从其他表中查询出相应的记录并插入到所创建的表中
#1.演示从本地装载数据到hive
#1.1创建表
create table student(id string, name string)
row format delimited fields terminated by '\t';
#1.2加载本地的文件到hive
load data local inpath
'/root/student.txt' into table default.student; #default.test 数据库.表名 也可直接表名
#2.演示加载HDFS文件到hive中
#2.1 将文件上传到HDFS根目录
dfs -put /root/student.txt /;
#2.2加载HDFS上的数据
load data inpath '/student.txt' into table test.student;
#3.加载数据覆盖表中原有的数据
#3.1上传文件到HDFS中
dfs -put /root/student.txt /; #将文件装载到表下 文件就相当于Windows中的剪切操作
#3.2加载数据覆盖表中原有数据
load data inpath '/student.txt' overwrite into table test.student;
#4.查询表
select * from student;
#通过查询语句向表中插入数据(insert)
#1.1创建表
create table student_par(id int,name String)
row format delimited fields terminated by '\t';
#1.2通过insert插入数据
insert into table student_par values(1,'zhangsan'),(2,'lisi');
Hive文件格式
TextFile:这是默认的文件格式。数据不会压缩处理,磁盘开销大,数据解析开销也大。
SequenceFile:这是HadooAPI提供的一种二进制文件支持,以二进制的形式序列化到文件中。
RCFile:这种格式是行列存储结构的存储方式。
ORC:ORC文件格式是一种Hadoop生态圈中的列式存储格式。ORC文件格式是以二进制方式存储的,所以是不可直接读取的。
ORC的优势
列示存储,有多种文件压缩方式
文件是可分割的。
提供了多种索引
可以支持复杂的数据结构 比如Map
Hive元数据的三种存储模式
单用户模式 : Hive安装时,默认使用的是Derby数据库存储元数据,这样不能并发调用Hive。
多用户模式 : MySQL服务器存储元数据
远程服务器模式 : 启动MetaStoreServer
Hive架构的组件
由上图可知,hadoop和mapreduce是hive架构的根基。Hive架构包括如下组件:CLI(command line interface)、JDBC/ODBC、Thrift Server、WEB GUI、metastore和Driver(Complier、Optimizer和Executor),这些组件可以分为两大类:服务端组件和客户端组件。
服务端组件
Driver组件:该组件包括Complier、Optimizer和Executor,它的作用是将我们写的HiveQL(类SQL)语句进行解析、编译优化,生成执行计划,然后调用底层的mapreduce计算框架。
Metastore组件:元数据服务组件,这个组件存储hive的元数据,hive的元数据存储在关系数据库里,hive支持的关系数据库有derby、mysql。元数据对于hive十分重要,因此hive支持把metastore服务独立出来,安装到远程的服务器集群里,从而解耦hive服务和metastore服务,保证hive运行的健壮性,这个方面的知识,我会在后面的metastore小节里做详细的讲解。
Thrift服务:thrift是facebook开发的一个软件框架,它用来进行可扩展且跨语言的服务的开发,hive集成了该服务,能让不同的编程语言调用hive的接口。
客户端组件
CLI:command line interface,命令行接口。
Thrift客户端:上面的架构图里没有写上Thrift客户端,但是hive架构的许多客户端接口是建立在thrift客户端之上,包括JDBC和ODBC接口。
WEBGUI:hive客户端提供了一种通过网页的方式访问hive所提供的服务。这个接口对应hive的hwi组件(hive web interface),使用前要启动hwi服务。
metastore组件详解
Hive的metastore组件是hive元数据集中存放地。Metastore组件包括两个部分:metastore服务和后台数据的存储。后台数据存储的介质就是关系数据库,例如hive默认的嵌入式磁盘数据库derby,还有mysql数据库。Metastore服务是建立在后台数据存储介质之上,并且可以和hive服务进行交互的服务组件,默认情况下,metastore服务和hive服务是安装在一起的,运行在同一个进程当中。我也可以把metastore服务从hive服务里剥离出来,metastore独立安装在一个集群里,hive远程调用metastore服务,这样我们可以把元数据这一层放到防火墙之后,客户端访问hive服务,就可以连接到元数据这一层,从而提供了更好的管理性和安全保障。使用远程的metastore服务,可以让metastore服务和hive服务运行在不同的进程里,这样也保证了hive的稳定性,提升了hive服务的效率。
用户接口组件:使用访问Hive有三种用户接口方式,使用shell命令行访问;通过网络上的客户端连接工具与Hive进行交互;第三种就是提供Web接口供编程语言进行接口访问
元数据存储组件:元数据是描述数据的数据,主要是描述数据属性的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。该组件包含用Hive创建的database、table、表的位置、类型、属性,字段顺序类型等元信息。元数据存储在关系型数据库中,如hive自带的关系型数据库Derby,或者可以自己搭建第三方关系型数据库MySQl等。该组件还包含一个元数据服务
Driver驱动程序:包括语法解析器、计划编译器、优化器、执行器
解析器(SQL Parser):将 SQL 字符串转换成抽象语法树 AST,这一步一般都用第三方工具库完成,比如 antlr;对 AST 进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误。
编译器(Physical Plan):将 AST 编译生成逻辑执行计划。
优化器(Query Optimizer):对逻辑执行计划进行优化。
执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。对于 Hive 来说,就是 MR/Spark。
执行引擎;Hive本身不直接处理数据文件,而是通过执行引擎处理。当下Hive支持MapReduce、Tez、Spark
Hive工作原理
简单来说Hive就是一个查询引擎。当Hive接受到一条SQL语句会执行如下操作:
词法分析和语法分析。使用antlr将SQL语句解析成抽象语法树
语义分析。从MetaStore中获取元数据信息,解释SQL语句中的表名、列名、数据类型
逻辑计划生成。生成逻辑计划得到算子树
逻辑计划优化。对算子树进行优化
物理计划生成。将逻辑计划生成出的MapReduce任务组成的DAG的物理计划
物理计划执行。将DAG发送到Hadoop集群进行执行
将查询结果返回。
执行过程
我们通过Hive的Client(Hive的命令行工具,JDBC等)向Hive提交SQL命令。如果是创建数据表的DDL(数据定义语言),Hive就会通过执行引擎Driver将数据表的信息记录在Metastore元数据组件中,这个组件通常用一个关系数据库实现,记录表名、字段名、字段类型、关联HDFS文件路径等这些数据库的Meta信息(元信息)。
如果我们提交的是查询分析数据的DQL(数据查询语句),Driver就会将该语句提交给自己的编译器Compiler进行语法分析、语法解析、语法优化等一系列操作,最后生成一个MapReduce执行计划。然后根据执行计划生成一个MapReduce的作业,提交给Hadoop MapReduce计算框架处理。
Hive如何实现join操作
除了简单的聚合(group by)、过滤(where)操作,Hive还能执行连接(join on)操作。
这两张表都有一个相同的字段userid,根据这个字段可以将两张表连接起来
SELECT pv.pageid, u.age FROM page_view pv JOIN user u ON (pv.userid = u.userid);
同样,这个SQL命令也可以转化为MapReduce计算,连接的过程如下图所示。
从图上看,join的MapReduce计算过程和前面的group by稍有不同,因为join涉及两张表,来自两个文件(夹),所以需要在map输出的时候进行标记,比如来自第一张表的输出Value就记录为<1, X>,这里的1表示数据来自第一张表。这样经过shuffle以后,相同的Key被输入到同一个reduce函数,就可以根据表的标记对Value数据求笛卡尔积,用第一张表的每条记录和第二张表的每条记录连接,输出就是join的结果。如果打开Hive的源代码,看join相关的代码,会看到一个两层for循环,对来自两张表的记录进行连接操作。
Hive的数据模型
Hive的数据模型类似于RDBMS库表结构,此外还有自己特有模型,Hive的数据在粒度上分为三类:Table表,Partition分区、Bucket桶
数据库(Database):Hive中也分多个数据库,可以理解为多个数据仓库。Hive的数据都是存储在HDFS上的
Table表:Hive表与关系数据库中的表相同,Hive中的表所对应的数据通常是存储在HDFS中,而表相关的元数据是存储在RDBMS中。怎么理解,就是说不管用户有多少个数据库(数据仓库),数据库下面有多少表,所有这些表只存储元数据信息,而所有表对应的数据都是存储在HDFS中的
Partitions分区:分区是一种优化手段,是指根据需要分区的列的值将表划分为不同分区,这样可以更快地对指定分区数据进行查询。
Buckets分桶:也是一种优化手段,是指根据表中字段的值,经过hash计算规则将数据划分为指定的若干个小文件,可以优化join查询和方便抽样查询。
Hive数据类型
Hive支持两种数据类型,一种原子数据类型、还有一种叫复杂数据类型。
原子数据类型
Hive类型中的String数据类型类似于MySQL中的VARCHAR。该类型是一个可变的字符串。
Hive支持数据类型转换,Hive是用Java编写的,所以数据类型转换规则遵循Java :
隐式转换 --> 小转大
强制转换 --> 大传小
复杂数据类型
Hive常用命令
将mysql中的数据直接保存到Hive中
sqoop export --connect jdbc:mysql://192.168.8.103:3306/hmbbs --username root --password hadoop --export-dir '/user/hive/warehouse/pv_2013_05_31/000000_0' --table pv
删除表中数据,但要保持表的结构定义
dfs -rmr /user/hive/warehouse/records;
显示所有函数
show functions;
查看函数用法
describe function substr;
内连接
SELECT sales.*, things.* FROM sales JOIN things ON (sales.id = things.id);
外连接
SELECT sales.*, things.* FROM sales LEFT OUTER JOIN things ON (sales.id = things.id);
查看hive为某个查询使用多少个MapReduce作业
Explain SELECT sales.*, things.* FROM sales JOIN things ON (sales.id = things.id);
显示表名的分区
show partitions 表名;
创建数据库
CREATE SCHEMA userdb;
删除数据库
DROP DATABASE IF EXISTS userdb;
DROP SCHEMA userdb;
创建数据表
use xxdb;
create table xxx; #内部表
创建一个表,结构与其他一样
create table xxx like xxx;
创建一个表,结构数据与其他一样,相当于复制一个表
create table xxx as xxx;
创建内部表
创建内部表,制定分隔符为tab键
create table tb_name(name1 int,name2 string) row format delimited fields terminated by '\t';
创建外部表
创建外部表 ,创建外部表的一般情况指的是:先有文件存放着数据,之后我们再来创建表,也就是说创建一张表,然后指向这个有数据的目录。以后只要是向这个目录中上传符合格式的数据会被自动装在到数据库表中,因为在metastore(元数据)会记录这些信息,创建外部表,制定分隔符为tab键
create external table tb_name(name1 int,name2 string) row format delimited fields terminated by '\t';
创建分区表
创建分区表,一般用于数据量比较大的情况下, partitioned by (logdate string)用来指定按照什么进行分区
创建分区:分区依据(Id int)
create table tb_name(
id int,
name string
) partitioned by (Id int)
row format delimited fields terminated by '\t';
普通表和分区表区别:有大量数据增加的需要建分区表
内外表转换
内部表转外部表
alter table table-name set TBLPROPROTIES('EXTERNAL'='TURE');
外部表转内部表
alter table table-name set TBLPROPROTIES('EXTERNAL'='FALSE');
删除分区
#注意:若是外部表,则还需要删除文件(hadoop fs -rm -r -f hdfspath)
alter table table_name drop if exists partitions (d='2016-07-01');
加载数据列表
把本地数据装载到数据表,也就是在metastore上创建信息
load data local inpath '/root/a.txt' into table tb_name;
把HDFS上的数据装载到数据表
load data inpath '/target.txt' into table tb_name;
加载数据到分区表必须指明所属分区
load data local inpath './book.txt' overwrite into table tb_name partition (Id = 10);
重命名表名
ALTER TABLE 表名1 RENAME TO 表名2;
删除表
drop table 表名;或者drop table if exists 表明;
插入表数据
向有分区的表插入数据
(1)覆盖现有分区数据,如果没有该指定分区,新建该分区,并且插入数据
INSERT OVERWRITE TABLE 库名.表名 PARTITION(dt='2018-09-12',name='Tom', ...)
SELECT ... FROM 库名.表名 where...
(2)向现有的分区插入数据 (之前的数据不会被覆盖)
INSERT INTO TABLE 库名.表名 PARTITION(dt='2018-09-12',name='Tom',...)
SELECT ... FROM 库名.表名 WHERE ...
向无分区的表插入数据
(1) 覆盖原有表里的数据,命令和有分区的表类似,只是去掉后面的PARTITION(dt=’ ‘,name=’')
INSERT OVERWRITE TABLE 库名.表名
SELECT ... FROM 库名.表名 where...
(2) 向现有的表插入数据 (之前的数据不会被覆盖)
INSERT INTO TABLE 库名.表名
SELECT ... FROM 库名.表名 WHERE ...
表结构修改
增加字段
alter table table_name add columns(newscol1 int conment '新增');
修改字段
alter table table_name change col_name new_col_name new_type;
删除字段
删除字段(COLUMNS中只放保留的字段)
alter table table_name replace columns(col1 int,col2 string,col3string);
字段类型
tinyint ,smallint,int,bigint,float,decimal,boolean,string
复合数据类型
struct,array,map
分桶表
对于每一个表或者分区,Hive可以进一步组织成桶,也就是说桶是更为细精度的数据范围划分。
桶的使用一定要设置如下属性:
hive.enforce.bucketing = true;
创建一个桶
# 按(id)分为4个bucket
create table tb_name (
id int,
name string
) clustered by (id) into 4 buckets
row format delimited fields terminated by ',';
通过子查询插入数据:
insert into tb_name1 select * from tb_name;
创建一个视图
create view v_name as
select table1.column1, table2.column2, table3.column3
where table1.column1 = table2.column2;
查看视图详细信息
describe extended valid_records;
更多命令好文参考:https://blog.csdn.net/qq_41094332/article/details/123122201