大数据学习之Hive框架整理

1、基本概念

1.1 定义

Hive:由Facebook开源用于解决海量结构化日志的数据统计。
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能。

本质是:将HQL转化成MapReduce程序
1)Hive处理的数据存储在HDFS
2)Hive分析数据底层的实现是MapReduce
3)执行程序运行在YARN上

1.2 优缺点

1.2.1优点
1)操作接口采用类SQL语法,提供快速开发的能力(简单、容易上手)
2)避免了去写MapReduce,减少开发人员的学习成本。
3)Hive的执行延迟比较高,因此Hive常用于数据分析,对实时性要求不高的场合;
4)Hive优势在于处理大数据,对于处理小数据没有优势
5)Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
1.2.2缺点
1)Hive的HQL表达能力有限
(1)迭代式算法无法表达
(2)数据挖掘方面不擅长
2)Hive的效率比较低
(1)Hive自动生成的MapReduce作业,通常情况下不够智能化
(2)Hive调优比较困难,粒度较粗

1.2.3框架原理
Hive通过给用户提供的一系列交互接口,接收到用户的指令(SQL),使用自己的Driver,结合元数据(MetaStore),将这些指令翻译成MapReduce,提交到Hadoop中执行,最后,将执行返回的结果输出到用户交互接口。

1)用户接口:Client
CLI(hive shell)、JDBC/ODBC(java访问hive)、WEBUI(浏览器访问hive)

2)元数据:Metastore

元数据包括:表名、表所属的数据库(默认是default)、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等;
默认存储在自带的derby数据库中,推荐使用MySQL存储Metastore

3)Hadoop
使用HDFS进行存储,使用MapReduce进行计算。

4)驱动器:Driver
(1)解析器(SQL Parser):将SQL字符串转换成抽象语法树AST,这一步一般都用第三方工具库完成,比如antlr;对AST进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误。
(2)编译器(Physical Plan):将AST编译生成逻辑执行计划。
(3)优化器(Query Optimizer):对逻辑执行计划进行优化。
(4)执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。对于Hive来说,就是MR/Spark。
Hive框架原理

1.4 Hive和数据库比较

由于 Hive 采用了类似SQL 的查询语言 HQL(Hive Query Language),因此很容易将 Hive 理解为数据库。其实从结构上来看,Hive 和数据库除了拥有类似的查询语言,再无类似之处。本文将从多个方面来阐述 Hive 和数据库的差异。数据库可以用在 Online 的应用中,但是Hive 是为数据仓库而设计的,清楚这一点,有助于从应用角度理解 Hive 的特性。

1.4.1查询语言
由于SQL被广泛的应用在数据仓库中,因此,专门针对Hive的特性设计了类SQL的查询语言HQL。熟悉SQL开发的开发者可以很方便的使用Hive进行开发。

1.4.2 数据存储位置
Hive 是建立在 Hadoop 之上的,所有 Hive 的数据都是存储在 HDFS 中的。而数据库则可以将数据保存在块设备或者本地文件系统中。

1.4.3 数据更新
由于Hive是针对数据仓库应用设计的,而数据仓库的内容是读多写少的。因此,Hive中不支持对数据的改写和添加,所有的数据都是在加载的时候确定好的。而数据库中的数据通常是需要经常进行修改的,因此可以使用 INSERT INTO … VALUES 添加数据,使用 UPDATE … SET修改数据。

1.4.4 索引
Hive在加载数据的过程中不会对数据进行任何处理,甚至不会对数据进行扫描,因此也没有对数据中的某些Key建立索引。Hive要访问数据中满足条件的特定值时,需要暴力扫描整个数据,因此访问延迟较高。由于 MapReduce 的引入, Hive 可以并行访问数据,因此即使没有索引,对于大数据量的访问,Hive 仍然可以体现出优势。数据库中,通常会针对一个或者几个列建立索引,因此对于少量的特定条件的数据的访问,数据库可以有很高的效率,较低的延迟。由于数据的访问延迟较高,决定了 Hive 不适合在线数据查询。

1.4.5 执行
Hive中大多数查询的执行是通过 Hadoop 提供的 MapReduce 来实现的。而数据库通常有自己的执行引擎。

1.4.6 执行延迟
Hive 在查询数据的时候,由于没有索引,需要扫描整个表,因此延迟较高。另外一个导致 Hive 执行延迟高的因素是 MapReduce框架。由于MapReduce 本身具有较高的延迟,因此在利用MapReduce 执行Hive查询时,也会有较高的延迟。相对的,数据库的执行延迟较低。当然,这个低是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。

1.4.7 可扩展性
由于Hive是建立在Hadoop之上的,因此Hive的可扩展性是和Hadoop的可扩展性是一致的(世界上最大的Hadoop 集群在 Yahoo!,2009年的规模在4000 台节点左右)。而数据库由于 ACID 语义的严格限制,扩展行非常有限。目前最先进的并行数据库 Oracle 在理论上的扩展能力也只有100台左右。

1.4.8 数据规模
由于Hive建立在集群上并可以利用MapReduce进行并行计算,因此可以支持很大规模的数据;对应的,数据库可以支持的数据规模较小。

2、Hive安装配置

详见 https://blog.csdn.net/weixin_44303896/article/details/103219260

3、数据类型

3.1基本数据类型


主要讲一下和java类型不同的:
Hive数据类型 Java数据类型
TINYINT short
SMALINT int
BIGINT long

额外提一下的:

Hive数据类型 备注
TIMESTAMP short
BINARY 字节数组
STRING 可以使用单引号或者双引号,相当于varchar可变字符串

3.2集合类型

Hive数据类型 描述
STRUCT :struct() 都可以通过“.”符号访问元素内容
MAP :map() 使用数组表示法可以访问数据,key->value,[‘key’] = value
ARRAY : Array() 通过数组名引用

集合使用

字段 解释
row format delimited fields terminated by ‘,’ 列分隔符
collection items terminated by ‘_’ MAP STRUCT 和 ARRAY 的分隔符(数据分割符号)
map keys terminated by ‘:’ MAP 中的key 与 value 的分隔符
lines terminated by ‘\n’; 行分隔符

3.3使用事例

理想中的数据结构(JSON表示)

{
	"name":"nameValue",
	"friends"["friend1","friend2".]
	"children":" {
		"children1" : 18,
		"children2" : 19
	}
	"address": {
	''street' : "streeValue",
	"city" : "cityValue"
	}
}

实际文件

nameValue,friend 1_friend2,children1:18_children2:19,streeVallue_cityValue
//新的一行数据 理论上没有备注所以 \n 切分行
nameValue2,friend 3_friend4,children5:18_children2:5,streeVallue2_cityValue2

Hive上创建测试表

//注意:MAP,STRUCT 和ARRAY 里的元素间关系都可以用同一个字符表示,这里用“_”
create table test( name string,
friends array<string>, children map<string, int>,
address struct<street:string, city:string>
)
row format delimited fields terminated by ','
collection items terminated by '_' map keys terminated by ':'
lines terminated by '\n';

3.4类型类型转化

隐式转化
可以自动转化为范围更广的类型,boolean不能转
CAST转化
CAST(‘1’ AS INT)将把字符串’1’ 转换成整数 1;如果强制类型转换失败,如执行CAST(‘X’ AS INT),表达式返回空值 NULL。

4.DDL数据定义

4.1 创建数据库

1)创建一个数据库,数据库在HDFS上的默认存储路径/user/hive/warehouse/*.db

2)避免要创建的数据库已经存在错误,增加if not exists判断,指定数据库在HDFS上存放的位置 [location '/db_hive2.db]

		hive (default)> create database if not exists db_hive [location '/db_hive2.db];

4.2 修改数据库

用户可以使用ALTER DATABASE命令为某个数据库的DBPROPERTIES设置键-值对属性值,来描述这个数据库的属性信息。数据库的其他元数据信息都是不可更改的,包括数据库名和数据库所在的目录位置。

hive (default)> alter database db_hive set dbproperties('createtime'='20170830');

4.3 查询数据库

4.3.2 查看数据库详情
显示数据库详细信息extended

hive> desc database extended db_hive;
OK
db_hive		hdfs://hadoop102:8020/user/hive/warehouse/db_hive.db	atguiguUSER	

4.4 删除数据库

如果删除的数据库不存在,最好采用 if exists判断数据库是否存在,如果数据库不为空,可以采用cascade命令,强制删除

		hive> drop database if exists db_hive2 cascade;

4.5 创建表

4.5.1语法
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
[(col_name data_type [COMMENT col_comment], …)] [COMMENT table_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment], …)]
[CLUSTERED BY (col_name, col_name, …)
[SORTED BY (col_name [ASC|DESC], …)] INTO num_buckets BUCKETS]
[ROW FORMAT row_format]
[STORED AS file_format]
[LOCATION hdfs_path]

  1. 字段解释说明
    (1) CREATE TABLE 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXISTS 选项来忽略这个异常。
    (2) EXTERNAL 关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION),Hive 创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。
    (3) COMMENT 为表和列添加注释。
    (4) PARTITIONED BY 创建分区表
    (5) CLUSTERED BY 创建分桶表
    (6) SORTED BY 不常用
    (7) ROW FORMA:
DELIMITED	[FIELDS	TERMINATED	BY	char]	[COLLECTION	ITEMS TERMINATED BY char]
[MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
| SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]

用户在建表的时候可以自定义 SerDe 或者使用自带的 SerDe。如果没有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,将会使用自带的 SerDe。在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的 SerDe,Hive 通过 SerDe 确定表的具体的列的数据。
SerDe 是 Serialize/Deserilize 的简称,目的是用于序列化和反序列化。
(8) STORED AS 指定存储文件类型
常用的存储文件类型:SEQUENCEFILE(二进制序列文件)、TEXTFILE(文本)、RCFILE(列式存储格式文件)如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩, 使用 STORED AS SEQUENCEFILE
(9) LOCATION :指定表在HDFS 上的存储位置。
(10) LIKE 允许用户复制现有的表结构,但是不复制数据。

4.5.2 管理表
1)理论
默认创建的表都是所谓的管理表,有时也被称为内部表。因为这种表,Hive会(或多或少地)控制着数据的生命周期。Hive默认情况下会将这些表的数据存储在由配置项hive.metastore.warehouse.dir(例如,/user/hive/warehouse)所定义的目录的子目录下。 当我们删除一个管理表时,Hive也会删除这个表中数据。管理表不适合和其他工具共享数据。
2)案例实操
查询表的类型

				hive (default)> desc formatted student2;

4.5.3 外部表
1)理论
因为表是外部表,所以Hive并非认为其完全拥有这份数据。删除该表并不会删除掉这份数据,不过描述表的元数据信息会被删除掉。

2)管理表和外部表的使用场景:
每天将收集到的网站日志定期流入HDFS文本文件。在外部表(原始日志表)的基础上做大量的统计分析,用到的中间表、结果表使用内部表存储,数据通过SELECT+INSERT进入内部表。

4.6 分区表

分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。在查询时通过WHERE子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多。
4.6.1 分区表基本操作
1)增加分区
同时创建多个分区 区之间用空格

			hive (default)>  alter table dept_partition add partition(month='201705')   partition(month='201704');

2)删除分区
同时删除多个分区,区之间用逗号隔开

			hive (default)> alter table dept_partition drop partition (month='201705'), partition (month='201706');

3)查看分区表有多少分区

hive>show partitions 

4)查看分区表结构

hive>desc formatted dept_partition

5)把数据直接上传到分区目录上,让分区表和数据产生关联的三种方式
(1)方式一:上传数据后修复
分区已存在,先传数据到已分区的文件夹再修复,分区一开始不存在,修复命令:msck repair
(2)方式二:上传数据后添加分区
文件夹存在,分区不存在,先将文件放到文件夹,在用hive命令添加分区
(3)方式三:上传数据后load数据到分区
文件夹分区都不存在,在hive用命令创建到分区文件夹,在load命令添加

4.7 修改表

4.7.1 重命名表
(1)语法

			ALTER TABLE table_name RENAME TO new_table_name

4.7.2 增加/修改/替换列信息
更新列

				ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name]

增加和替换列,ADD是代表新增一字段,字段位置在所有列后面(partition列前),REPLACE则是表示替换表中所有字段。

				ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...) 

5、 DML数据操作

5.1 数据导入

5.1.1 向表中装载数据(Load)
语法
hive>load data [local] inpath ‘/opt/module/datas/student.txt’ [overwrite] into table student [partition (partcol1=val1,…)];
(1)load data:表示加载数据
(2)local:表示从本地加载数据到hive表;否则从HDFS加载数据到hive表
(3)inpath:表示加载数据的路径
(4)overwrite:表示覆盖表中已有数据,否则表示追加
(5)into table:表示加载到哪张表
(6)student:表示具体的表
(7)partition:表示上传到指定分区

5.1.2 通过查询语句向表中插入数据(Insert)
hive (default)> from student
insert overwrite table student partition(month=‘201707’)
select id, name where month=‘201709’
insert overwrite table student partition(month=‘201706’)
select id, name where month=‘201709’;
5.1.3 查询语句中创建表并加载数据(As Select)
create table if not exists student3 as select id, name from student;

5.1.5 Import数据到指定Hive表中
注意:先用export导出后,再将数据导入。

5.2 数据导出

5.2.1 Insert导出local决定导出到本地还是hdfs

hive (default)> insert overwrite local directory '/opt/module/datas/export/student1'
         ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
         select * from student;

5.2.2 Hadoop命令导出到本地

hive (default)> dfs -get /user/hive/warehouse/student/month=201709/000000_0  /opt/module/datas/export/student3.txt;

5.2.3 Hive Shell 命令导出

[atguigu@hadoop102 hive]$ bin/hive -e 'select * from default.student;' >> /opt/module/datas/export/student4.txt;

5.2.4 Export导出到HDFS上

hive (default)> export table default.student to '/user/hive/warehouse/export/student';

5.2.5 Sqoop导出

5.3 清除表中数据(Truncate)

Truncate只能删除管理表,不能删除外部表中数据

	hive (default)> truncate table student;

6、查询(记得善用子查询)

[WITH CommonTableExpression (, CommonTableExpression)*]    (Note: Only available starting with Hive 0.13.0)
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
  FROM table_reference
  [WHERE where_condition]
 [GROUP BY col_list]
 [ORDER BY col_list]
  [CLUSTER BY col_list | [DISTRIBUTE BY col_list] 
  [SORT BY col_list] ]
  [LIMIT number]
Like和RLike
1)使用LIKE运算选择类似的值
2)选择条件可以包含字符或数字:
	% 代表零个或多个字符(任意个字符)。
	_ 代表一个字符。
3)RLIKE子句是Hive中这个功能的一个扩展,其可以通过Java的正则表达式这个更强大的语言来指定匹配条件。
Join语句

满外查询full join :没有符合的值用null代替

6.5 排序

6.5.1 全局排序(Order By)
Order By:全局排序,一个MapReduce
1)使用 ORDER BY 子句排序
ASC(ascend): 升序(默认)
DESC(descend): 降序
2)ORDER BY 子句在SELECT语句的结尾。
3)案例实操

6.5.2 每个MapReduce内部排序(Sort By)
Sort By:每个MapReduce内部进行排序,对全局结果集来说不是排序,设置reduce个数

hive (default)> set mapreduce.job.reduces=3;

6.5.3 分区排序 Distribute By
Distribute By:类似MR中partition,进行分区,结合sort by使用。
注意,Hive要求DISTRIBUTE BY语句要写在SORT BY语句之前。

6.5.4 Cluster By
当distribute by和sorts by字段相同时,可以使用cluster by方式。
cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。
1)以下两种写法等价

select * from emp cluster by deptno;
select * from emp distribute by deptno sort by deptno;

注意:按照部门编号分区,不一定就是固定死的数值,可以是20号和30号部门分到一个分区里面去。

6.6 分桶及抽样查询

6.6.1 分桶表数据存储
分区针对的是数据的存储路径;分桶针对的是数据文件。
分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理的分区,特别是之前所提到过的要确定合适的划分大小这个疑虑。
分桶是将数据集分解成更容易管理的若干部分的另一个技术。

方法 先设置参数,在通过子查询写入

hive (default)>set hive.enforce.bucketing=true;
hive (default)> set mapreduce.job.reduces=-1;
hive (default)>insert into table stu_buck
select id, name from stu;

6.6.2 分桶抽样查询

hive (default)> select * from stu_buck TABLESAMPLE(bucket 1 out of 4 on id);

注:tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y) 。
y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。例如,table总共分了4份,当y=2时,抽取(4/2=)2个bucket的数据,当y=8时,抽取(4/8=)1/2个bucket的数据。

x表示从哪个bucket开始抽取,如果需要取多个分区,以后的分区号为当前分区号加上y。例如,table总bucket数为4,tablesample(bucket 1 out of 2),表示总共抽取(4/2=)2个bucket的数据,抽取第1(x)个和第4(x+y)个bucket的数据。

注意:x的值必须小于等于y的值
6.6.3 数据块抽样
Hive提供了另外一种按照百分比进行抽样的方式,这种事基于行数的,按照输入路径下的数据块百分比进行的抽样。

	hive (default)> select * from stu tablesample(0.1 percent);

提示:这种抽样方式不一定适用于所有的文件格式。另外,这种抽样的最小抽样单元是一个HDFS数据块。因此,如果表的数据大小小于普通的块大小128M的话,那么将会返回所有行。

6.7 行转列

相关函数说明
1)CONCAT(string A/col, string B/col…):返回输入字符串连接后的结果,支持任意个输入字符串;
2)CONCAT_WS(separator, str1, str2,…):它是一个特殊形式的 CONCAT()。第一个参数剩余参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;
3)COLLECT_SET(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段。

6.8列转行(将单元格炸开)

相关函数说明
1)LATERAL VIEW:
用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias
解释:用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。
2)EXPLODE(col):将hive一列中复杂的array或者map结构拆分成多行。

select
movie,
category_name 
from 
movie_info lateral view explode(category) table_tmp as category_name;

6.9开窗函数

相关函数说明
1)OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化
2)CURRENT ROW:当前行
3)PRECEDING n:往前n行数据
4)FOLLOWING n:往后n行数据
5)UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING表示到后面的终点
6)LAG(col,n):往前第n行数据
7)LEAD(col,n):往后第n行数据
8)NTILE(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。注意:n必须为int类型。

7、函数

7.1 自定义函数

1)Hive 自带了一些函数,比如:max/min等,但是数量有限,自己可以通过自定义UDF来方便的扩展。
2)当Hive提供的内置函数无法满足你的业务处理需要时,此时就可以考虑使用用户自定义函数(UDF:user-defined function)。
3)根据用户自定义函数类别分为以下三种:
(1)UDF(User-Defined-Function)
一进一出
(2)UDAF(User-Defined Aggregation Function)
聚集函数,多进一出
类似于:count/max/min
(3)UDTF(User-Defined Table-Generating Functions)
一进多出
如lateral view explore()
4)官方文档地址
https://cwiki.apache.org/confluence/display/Hive/HivePlugins
5)编程步骤:
(1)继承org.apache.hadoop.hive.ql.UDF
(2)需要实现evaluate函数;evaluate函数支持重载;
(3)在hive的命令行窗口创建函数
a)添加jar
add jar linux_jar_path
b)创建function,
create [temporary] function [dbname.]function_name AS class_name;
(4)在hive的命令行窗口删除函数
Drop [temporary] function [if exists] [dbname.]function_name;
6)注意事项
(1)UDF必须要有返回类型,可以返回null,但是返回类型不能为void;
7.3 自定义UDF函数开发案例
1)创建一个java工程,并创建一个lib文件夹
2)将hive的jar包解压后,将apache-hive-1.2.1-bin\lib文件下的jar包都拷贝到java工程中。
3)创建一个类

package com.atguigu.hive;
import org.apache.hadoop.hive.ql.exec.UDF;

public class Lower extends UDF {

	public String evaluate (final String s) {
		
		if (s == null) {
			return null;
		}
		
		return s.toString().toLowerCase();
	}
}

4)打成jar包上传到服务器/opt/module/jars/udf.jar
5)将jar包添加到hive的classpath
hive (default)> add jar /opt/module/datas/udf.jar;
6)创建临时函数与开发好的java class关联
hive (default)> create temporary function udf_lower as “com.atguigu.hive.Lower”;
7)即可在hql中使用自定义的函数strip
hive (default)> select ename, udf_lower(ename) lowername from emp;

8、压缩和储存

之后再说

9、企业调优

之后再说

发布了11 篇原创文章 · 获赞 14 · 访问量 260

猜你喜欢

转载自blog.csdn.net/weixin_44303896/article/details/103303828