认识Hive,以及Hive的数据定义与数据操作,hive的数据查询和hive函数

孤街浪徒 提交于 2020-10-24 17:19:08

认识Hive

为什么要出现hive
前面知识我们讲到mapreudce计算框架,各位需要通过java编码的形式来实现设计运算过程,这对各位的编程能力提出了更高的要求,难道没有门槛更低的方式来实现运算的设计吗?Hive出现的目的就是为了解决这个问题。
Hive的设计目的是为了让那些精通SQL技能而Java技能较弱的数据分析师能够利用Hadoop进行各种数据分析。
对于前面的WordCount例子,Java代码大概在80行左右,这对于经验丰富的Java开发工程师来说也不是易事,但如果用Hive的查询语言(即HiveQL)来完成的话,只有几行代码:
在这里插入图片描述
可以看出HiveQL的语法和SQL非常类似。在实际开发中,80%的操作都不会由MapReduce程序直接完成,而是由Hive来完成,所以Hive本身实践性非常强,并且使用频率非常高,只需要对SQL熟练即可
简单来说就是为了那些精通sql的人哈!!
Hive显著地降低了使用Hadoop来做数据分析的学习成本,对于精通Java的人来说,Hive任然是首选,因为Hive稳定,代码精简并且易于维护。
常用的count、group by、order by、join等SQL操作都可以由Hive来完成,在某种意义上,Hive可以说是HiveQL(SQL)到Mapreduce的映射器,或者说是对Mapreduce任务的高度封装
Hive可以将用户输入的HiveQL脚本转化为一个或多个MapReduce作业并在集群上运行。
在这里插入图片描述
HQL被转化为一个MapReduce作业执行,执行时与普通MapReduce作业一样,也是分为map和reduce部分,还可以通过Hadoop的Web UI查看作业
在这里插入图片描述
但是也不是所有的hive都会执行MaperReduce任务!例如:
select * from 表名;
这种HQL是不会被Hive转化为MapReduce作业执行的,Hive只会将该表所分布在各个DataNode的数据拉到Hive所有节点并依次输出。














与Hadoop的HDFS和MapReduce计算框架不同,Hive并不是分布式,它独立于集群之外,可以看作是一个Hadoop的客户端.
在这里插入图片描述

Hive的架构

可以通过CLI(命令行接口)、HWI(Hive网络界面)以及Thrift Server提供的JDBC和ODBC的方式访问Hive,其中最常见的是Hive命令行接口。用户通过以上方式向Hive提交查询命令,而命令会进入Driver模块、通过该模块对命令进行解释和编译,对需求的计算进行优化,然后按照生成的执行计划执行,执行计划会将查询分解为若干个MapReduce作业。
Hive通过与Yarn通信来初始化MapReduce作业,所以Hive并不需要部署在Yarn节点,通常在大型的生产环境集群,Hive被独立部署在集群之外的节点。
Metastore是Hive的元数据的集中存放地,它保存了Hive的元数据信息,如表名、列名、字段名等,它对于Hive是一个非常重要的组成。它包括两个部分、元数据服务和元数据存储。Hive将HDFS上的结构化的数据通过HQL对数据进行查询。Hive的元数据存储通常由一个关系型数据库完成(如MySQL、PostgreSQL、Oracle等)。

Hive的三种安装模式

内嵌模式
*第一种是内嵌模式,这是最简单的模式,元数据服务和Hive服务和Hive服务运行在同一个JVM中,同时使用内嵌的Derby数据库作为元数据存储,该模式最能支持同时最多一个用户打开Hive会话。
在这里插入图片描述

本地模式
第二种是本地模式,可以看到Hive服务和元数据服务器仍运行在同一个JVM中,不同的是,采用了外置的MySQL作为元数据存储,该方法支持多个用户同时访问Hive.
在这里插入图片描述
远程模式
三种模式是远程模式,这种模式下元数据服务和Hive服务运行在不同的进程内,这样的好处是,数据库层可以完全地置于防火墙之后,客户端则不需要数据库验证。在生产环境中,推荐使用本地模式和远程模式
在这里插入图片描述
~~





Hql与Sql非常相似,但是hive和关系型数据库除了查询语句非常类似,再无其他类似!!!

~~ 区别
在这里插入图片描述
1数据存储位置。
Hive是基于Hadoop的,所有Hive的数据都是存储在HDFS中的,而数据库则可以将数据保存在块设备或者本地文件系统中
数据格式
对于Hive的数据格式,用户可以自由定义行列的分隔符,由用户自己指定,而关系型数据库都有自己的存储引擎,所有的数据都会安装一定组织存储
数据更新
Hive是基于Hadoop的,并且Hive的用处是作为数据仓库,它们的特征都是”一次写入,多次读取”,所以Hive是不支持数据更新和添加的,所有数据在加载时就已经确定,不可更改,而关系型数据库可以通过Update…Set或Insert Into…Values添加和修改数据。
索引
Hive在加载数据的过程中不会对数据进行任何处理,甚至不会对数据进行扫描,因此也没有对数据中的某些列建立索引。
执行
Hive中大多数查询的执行是通过Hadoop提供的MapReduce计算框架来实现的,而数据库通常有自己的执行引擎。
执行延迟
Hive没有索引,所以在查询数据的时候必须进行全表扫描,因此延迟较高。另一个原因导致Hive执行延迟高因素是MapReduce计算框架,MapReduce技术框架本身也具有较高延迟。相比来说,数据库的执行延迟较低。
可扩展性
Hive是基于Hadoop的,因此Hive的可扩展性与Hadoop的可扩展性是一致的。而数据库扩展能力非常有限,目前最先进的Oracle并行数理论上也只能扩展到100台左右。
数据规模
Hive建立在集群上并可以利用Mapreduce进行并行计算,因此可以支持很大规模的扩展。相应的,数据库可以支持的数据规模较小。
从以上的不同点可以发现,对于面向小数据量、查询延迟敏感的关系型数据库更适用于在线数据处理。而面向大数据量、查询延迟不敏感的Hive更适用于离线数据分析。

















Hive的数据定义

可以使用create database 语句来创建数据库
在这里插入图片描述
如果test数据库已经存在,将抛出错误信息
在这里插入图片描述
可以使用 show databases语句查看已经存在的数据库
在这里插入图片描述
Hive会为每个创建的数据库在HDFS上创建一个目录,该数据库中的表会以子目录的形式存储,表中的数据会以表目录下的文件的形式存储。如果用户使用default数据库,该数据库本身没有自己的目录。数据库所在目录在hive-site.xml文件中的配置项hive.metastore.warehouse.dir配置的目录之后,默认是/user/hive/warehouse:
在这里插入图片描述
test.db是test数据库的数据库目录,而该数据库中的表将以子目录的形式存放在test.db目录中.注意.数据库目录的名字都是以.db结尾。
如果想针对某个数据库改变其存放位置,可以使用如下命令在建表的时候修改默认存放位置








在这里插入图片描述
如果想查看某个已经存在的数据库,可以使用如下命令
在这里插入图片描述
和mysql类似,也可以切换当前工作的数据库,如下:
在这里插入图片描述
当需要删除某个数据库时,如下
在这里插入图片描述
hive中的表
可以用show tables 或者show tables in test(test 为数据库下的表)
在这里插入图片描述
创建表
在这里插入图片描述
如果用户加上if not exists,那么当该表存在时,Hive会忽略掉后面的命令,但是有一点需要注意,当存在的表的数据结构和需要创建的表的数据结构有所不同,那么Hive会忽略掉这个差异,并不会做出任何提示。
如果用户的当前数据库非目标数据库,必须在表名加上数据库的名字来指定,上面这个例子指定的数据库为test,需要创建的表名为student,或者使用Hive的命令:
hive>use test;
在建表之前先切换到目标数据库
可以对表的字段和表添加注释,在需要添加注释的字段后面加上”COMMENT……”,表级别的注释则在申明完全部字段后,加上”COMMENT….”这在实际开发中是非常必要的。当想查看注释信息时,可以使用Hive命令:




在这里插入图片描述
在这里插入图片描述
如果想要查看表级别的注释,则需要使用Hive命令:
hive>desc extended student; 或者 hive>desc formatted student;
在这里插入图片描述
在这里插入图片描述
这两个命令将会把表的详细信息输出到控制台,在实际情况中,后者用处要多一些,因为其信息更全且可读性更好
可以使用row format delimited、stored as 等子句指定行列的数据格式和文件的存储格式,也可以省略不写使用Hive提供的默认值。
location子句可以指定该表的存储位置,如果不写,将会存储在Hive默认的数据仓库目录。
还可以通过复制另外一张表的表结构(不复制数据)的方法来创建表,如下:
hive>create table if not exists test.students like test.student;






















hive 中的数据类型

Hive 的内置数据类型分为两大类

1,基本的数据类型
其中,基础数据类型包括:TINYINT,SMALLINT,INT,BIGINT,BOOLEAN,FLOAT,DOUBLE,STRING,BINARY,TIMESTAMP,DECIMAL,CHAR,VARCHAR,DATE。下面的表格列出这些基础类型所占的字节以及从什么版本开始支持这些类型
在这里插入图片描述

2,复杂数据类型
复杂类型包括ARRAY,MAP,STRUCT,UNION,这些复杂类型是由基础类型组成的

ARRAY
ARRAY类型是由一系列相同数据类型的元素组成,这些元素可以通过下标来访问。比如有一个ARRAY类型的变量fruits,它是由[‘apple’,‘orange’,‘mango’]组成,那么我们可以通过fruits[1]来访问元素orange,因为ARRAY类型的下标是从0开始的;

MAP
MAP包含key->value键值对,可以通过key来访问元素。比如”userlist”是一个map类型,其中username是key,password是value;那么我们可以通过userlist[‘username’]来得到这个用户对应的password;
STRUCT
STRUCT可以包含不同数据类型的元素。这些元素可以通过”点语法”的方式来得到所需要的元素,比如user是一个STRUCT类型,那么可以通过user.address得到这个用户的地址。


Hive表的类型

管理表
Hive中,在创建表时,如果没有特别指明的话,都是Hive中所谓的管理表(managed table),也叫托管表,表管理意味着由Hive负责管理表的数据,Hive默认会数据保存到数据仓库目录下,当删除管理表时,Hive将删除管理表的数据和元数据.
外部表
如果当一份数据需要被多种工具分析时,如Pig、Hive,意味着这份数据的所有权并不由Hive拥有。这时可以创建一个外部表(External Table)指向这份数据,如下:
在这里插入图片描述
关键字external指明该表为外部表,而location子句指明了数据存放的HDFS的/user/test/x目录下
当需要删除外部表时,Hive会认为没有完全拥有这份数据,所以Hive只会删除该外部表的元数据信息而不会删除该表的数据。
管理表和外部表的差异并不能从表数据是否保存在Hive默认的数据参考目录下来判断,即使是管理表,在建表时也可以通过指定location子句指定存放路径。一般来说,当数据需要被多个工具共享时,最好创建一个外部表来明确数据的所有权。
分区表
Hive可以支持对进行分区(partition),分区可以将表进行水平切分,将表数据按照某种规则进行存储,分区表相对于没有分区的表有明显的优势,所以在实际生产环境中,分区表使用的非常普遍。
在这里插入图片描述
通过partitioned by子句指定表按照学生家庭住址的city和province字段进行分区,此处注意定义分区的字段不能和定义表的字段重合,否则会出现”column repeated in partitioniong colums”的错误信息。Hive中表是以目录形式存在,二表的分区则是以表的目录的子目录存在,例如,该学生信息表保持了某高校所有在校生信息,那么在该表目录下,数据是这样组织的:
在这里插入图片描述
可以看见,分区将表水平切分为若干个文件,而切分的规则就是分区的字段,如上,所有学生的信息按照省、市的不同分别保存在不同的目录下。
分区表和为分区表的性能差别很大
hive>select * from student_info where province=’sichuan’ and city=’chengdu’
由于分区表将所有provice=’sichuan’和city=’chengdu’的数据都存在一个目录下,所有Hive只会扫描文件夹下的数据,对于大数据集,分区表可以显著提升查询性能,因为如果没有分区,Hive将不得不进行全表扫描。虽然提到Hive没有索引,但是分区的作用和索引非常类似,我们可以姑且将其看做一种简易索引。对于直接命中分区的查询,Hive不会执行MapReduce作业.
一般情况下,在生产环境中,由于业务数据量非常巨大,所以都会对表进行分区,最常见的是按照创建时间或者是修改时间进行分区
可以通过show partitions student_info来显示student_info的分区情况,还可以通过describe extended student_info来查看分区表的详细信息
外部表也是可以有分区的,并且由于外部表可以自定义目录结构,所有外部表更加灵活.
**在这里插入图片描述
**和普通外部表不同的是,在建表时并没有指定表的存储路径,所有在创建完外部分区表后,如果执行查询语句是查不到任何数据的,就需要单独为外部表的分区键指定值和存储位置:
alter table student_info add partition (province=sichuan,city=chengdu) location ‘hdfs://master:9000/student/sichuan/chengdu’
从上面可以看出,外部表的目录结构可以完全由自己指定。同其他外部表一样,即使外部分区表被删除,数据也不会被删除。
无论是管理表还是外部表,一旦给表存在分区,那么数据在加载时必须加载进入制定分区中:
load data inpath ‘/user/hadoop/data’ into student_info partition(province=’sichuan’,city=’chengdu’)
**
删除表
同SQL一样,Hive删除表的方式为:
drop table test;
或者
drop table if exists test;
修改表
在Hive中,可以使用alter table子句来修改表属性,在前面已经使用它为表增加了一个分区。alter table意味着该子句仅仅修改表的元数据,而不会修改表本身的数据。
表重命名
alter table test rename to test2
增加、修改和删除表分区
增加分区(通常是外部表):

alter table test add partition (x=x1,y=y2) location ‘/user/test/x1/y1’
修改分区:
alter table test add partition (x=x1,y=y2) set location ‘/user/test/x1/y1’
该命令修改已存在的分区路径。
删除分区:
alter table test drop partition (x=x1,y=y2)
修改列信息
用户可以对某个字段(列)进行重命名,并修改其数据类型、注释、在表中的位置:
alert table test
change column id uid int
comment ‘the unique id’
after name;
上面这个例子是将test表中的id字段重命名为uid,并指定其类型为int(即使类型和原来一样,也需要新指定),并注释为the unique id,最后再将该字段移动到name字段之后.
增加列
alert table test add columns (new_col int ,new_col2 string)
删除或者替换列
alert table test replace colums (new_col int ,new_col2 string);
该命令删除了test表的所有列并重新定义了字段,由于知识改变了元数据,表数据并不会因此而丢失和改变。
一定切记aleter table 只是修改了表的元数据,所有一定要保证表的数据和修改后的元数据模式要匹配,否则数据将会变的不可用

在创建完表后,就应该对表中的数据进行相关操作,但是Hive不支持行级别的删改,也就是传统关系型数据库中的update、delete操作是不支持的。支持的只有转载数据,导出数据和查询数据操作






















































Hive 的数据操作

装载数据
在Hive中装载数据可以理解为传统关系型数据库中的添加数据,但是原理是完全不同的。Hive中有五种装载数据的方式
创建一张表:person

在这里插入图片描述
hdfs的put命令上传文件
由于hive本质就是hdfs的目录,所有可以通过直接操作hdfs目录的方式控制hive
创建一个文本文件person.txt,格式如下:
在这里插入图片描述
使用hdfs命令上传文件到hive创建好的数据库person对应的目录下
在这里插入图片描述
在这里插入图片描述
使用查询语句进行查看
在这里插入图片描述
load data命令方式
首先上传文件到hdfs文件系统










在这里插入图片描述
在hive提示符下
在这里插入图片描述
使用查询语句进行查看
在这里插入图片描述
这条命令将HDFS的/user/person文件夹下的所有文件追加到表test中,如果需要覆盖test表已有的记录,则需要overwrite关键字,如下:
load data inpath ‘/user/person’ overwrite into table test;
如果test表是一个分区表,则在HQL表中必须指定分区,如下:
load data inpath ‘/user/person’ overwrite into table test3 partition (part=”a”)
Hive也支持从本地直接加载数据到表,只需要加上local关键字即可:
load data local inpath ‘/home/person’ into table test;
load data local inpath ‘/home/person’ overwrite into table test;
如果加上关键字local,Hive会将本地文件复制一份再上传至指定目录,如果不加local关键字,Hive只是将HDFS上的数据移动到指定目录。
Hive在加载数据时不会对数据格式进行任何的验证,需要用户自己保证数据格式与表定义的格式一致。
插入单条数据
在这里插入图片描述
在这里插入图片描述
通过查询语句想表中插入数据
Hive支持通过查询语句向表中插入数据,如下:
insert overwrite table test select * from source;
同样,当test表示分区表时,必须指定分区:
insert overwrite table test partition (part=’a’) select id,name from source;
Hive还有一个很有用的特性,可以通过一次查询,产生多个不相交的输出,如下
在这里插入图片描述
这样只通过source表的一次查询,就将符合条件的数据插入test表的各个分区,非常方便,如果要使用Hive这个特性,则必须将from子句写在前面。
cats命令方式
cats是create table …as select的缩写,意味着在一条语句中创建表并加载数据,Hive支持这样的操作,如下:
create table test as select id,name from source;
导出数据
可以通过查询语句选取需要的数据格式,再用insert子句将数据导出至HDFS或是本地,如下:
insert overwrite directory ‘/user/hadoop/r’ select * from test;
insert overwrite local directory ‘/home/hadoop/r’ select * from test;
如果Hive表中的数据正好满足用户需要的格式,那么直接复制文件或者目录就可以了,如下:
hadoop dfs -cp /user/hive/warehoures/source_table /user/hadoop/
Hive不支持数据增加、删除和修改操作,只能对数据进行加载和导出以及查询相关操作,本质上是对HDFS中hive目录下的文件进行新增,删除,复制等操作。

































Hive的数据查询和Hive函数

数据查询是Hive最主要的功能。Hive不支持标准SQL,但是熟悉SQL的开发者还是能很快上手
select…from语句
select后面跟查询的字段,from子句后面跟查询的表名,如下:
select 字段A,字段B from 表名;
在这里插入图片描述
还可以为列和表加上别名,如下:
在这里插入图片描述
需要结果集的部分数据,可以通过limit子句来限制返回的行数 如下
select * from 表名 limit 2;
这时候返回就是前2条
在这里插入图片描述
在select语句中使用case…when…then
在select语句中根据某列进行相应的处理

在这里插入图片描述
**语句:
select id,name,sex,
case
when sex=’m’ then ‘男’
when sex=’F’ then ‘女’
else ‘无数据’
end
from student;
**




















where 语句:很多时候需要对条件进行限制,就需要使用where语句,例如:select * from 表名 where age =18;
where 后可以跟的表达式完全兼容sql 的写法: =,<,>!=,<=,>=,is null,is not null ,like,between,or,and,in
在这里插入图片描述
在这里插入图片描述
group by和 having by语句
group by 通常会和聚合函数一起使用,先按照一个列或多个列对结果进行分组,再执行聚合操作,如下:
select count(*) from student group by age;
在这里插入图片描述
select avg(age) from 表名 gruop by bady;
在这里插入图片描述
如果使用group by 子句,那么查询的字段如果没有出现在group by子句的后面,则必须使用聚合函数,如下:
select name,avg(age) from student group by body;
这样,Hive就会抛出一个Expression not in group by key name的异常。
在这里插入图片描述
如果想对分组的结果进行条件过滤,可以使用having子句,如下













select course,avg(age) from student where body= “ok” group by course having avg(age) >18;
**ps :注意:字符串不能使用’’号必须使用””号
**
在这里插入图片描述
join语句
1,inner join(内连连接)
select t1.name,t2.wscore,t2.lscore from student t1 inner join score t2 on t1.sid = t2.sid
在这里插入图片描述
在这里插入图片描述
2,left/right outer join(左右外连接)
select t1.name,t2.wscore from student t1 left outer join score t2 on t1.sid = t2.sid;
在这里插入图片描述
在这里插入图片描述
select t1.name,t2.wscore from student t1 right outer join score t2 on t1.sid = t2.sid;
在这里插入图片描述
在这里插入图片描述
full outer join(全外连接)
与左/右连接类似,全外连接意味着结果集会包含左表和右表的所有记录,如下:
select t1.name,t2.wscore from student t1 full outer join score t2 on t1.sid = t2.sid;
在这里插入图片描述
在这里插入图片描述
left semi join(左半连接)
左半连接是Hive特有的语法相当于标准SQL的子查询,会返回左表的记录,前提是其记录对于右边表满足on语句中的判断条件.左半连接被用来代替标准SQL中的in的操作,如下:
select t1.name from student t1 left semi join score t2 on t1.sid = t2.sid;
在这里插入图片描述
在这里插入图片描述
该操作不能使用标准SQL中的in操作来完成,如下:
select t1.name from student where t1.sid in (select t2.sid where score)
这样的写法Hive是不支持的。
当然完全可以通过内连接得到同样的结果,如下:
select t1.name from student t1 inner join score t2 on t1.sid = t2.sid;
但是左半连接通常比内连接要高效,因为对于左表中的一条指定的记录,在右表中一旦找到匹配的记录,Hive就会停止扫描.
多表join
Hive可以支持多表进行join,如下:
select * from table1 t1
join table2 t2 on t1.id = t2.id
join table3 t3 on t1.id = t3.id



































order by 和 sort by 语句
Hive中的order by 和 SQL中的order by的语义是一样的,执行全局排序,这样就必须有一个Reducer来完成,否则无法达到全局排序的要求,如下:
在这里插入图片描述
在这里插入图片描述
**在排序的时候可以使用desc 和asc 关键字 指定排序方式,Hive还有一种排序方式,这种排序方式只会在每个Reducer中进行一个局部排序,也就是sort by 如下:
**
在这里插入图片描述
在这里插入图片描述
因为当前是伪分布式配置所以Reducer只有1个。
两种排序方式语法结构完全一样,当Reducer的个数只有1个时,两种结果完全相同。当Reducer的个数不止一个,sort by
输出可能会有重合。
在这里插入图片描述
distribute by 和 sort by 语句











distribute by对于Hive的意义等同于Partitioner对于MapReduce的意义,通过distribute by可以自定义分发规则从而使某些数据进入同一个Reducer,这样通过sort by以后,就可以得到想要的结果。
如果只希望第一列相同的数据能够按第二列进行排序的话,就可以通过distribute by和sort by完成,如下:
select coure, age from student distribute by coure sort by coure,age;
在这里插入图片描述
在这里插入图片描述
distribute by保证了coure相同的数据一定进入同一个Reducer,在Reducer中再按照coure、age的顺序即可达到要求。




cluser by
如果在使用distribute by和sort by语句时,distribute by和sort by涉及的列完全相同,并且采用升序排列,可以使用cluster by代替distribute by 和sort by.

**union all Hive中对于union all的使用是非常常见的,主要用于多表合并的场景。union all要求各表select出的字段必须完全匹配
**

在这里插入图片描述
在这里插入图片描述

Hive函数

Hive内置了许多函数(类似sqlserver中的getDate()以及时间函数,数学函数等等),在数据查询操作中经常会用到,可以通过show functions来查看内置的函数。Hive内置的函数主要分为一下3类:标准函数、聚合函数和表生产函数
内置函数
博主懒得写这个了,这个比较简单哈!!码太多字了
聚合函数
count 计算总行数
在这里插入图片描述
在这里插入图片描述
sum :计算指定列的和
在这里插入图片描述
在这里插入图片描述
avg 计算制定列的平均数
在这里插入图片描述
在这里插入图片描述
max/min 统计指定列的最大值、最小值
在这里插入图片描述
在这里插入图片描述
表生成函数
表生成函数:可以理解为一个函数可以生成一个表
行转列函数–explode(字段名–hive中集合类型中的array,map)----炸开字段内容
在这里插入图片描述
在这里插入图片描述
用户定义的函数这个不介绍了哈!!!
**加粗样式
**






















  • 总结
  • hive的数据查询
  • hive函数
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!