Hive 数仓

Hive 是什么?

Hive 是一个构建在 Hadoop 之上的数据分析工具(Hive 没有存储数据的能力,只有使用数据的能力), 底层由 HDFS 来提供数据存储,可以 将结构化的数据文件映射为一张数据库表,并且提供类似 SQL 的查询功能,本质就是将 HQL 转化成 MapReduce 程序。Hive 是一个将 SQL 转换为 MapReduce 程序的工具,甚至更近一步说 Hive 就是一个 MapReduce 客户端。

总结:交互方式采用 SQL,元数据存储在 Derby 或 MySQL,数据存储在 HDFS,分析数据底层实现是 MapReduce,执行程序运行在 YARN 上。

Hive 与 数据库 的区别

为什么使用Hive

相对于 Hadoop-MapReduce 而言减少学习成本,因为要学习 Java 或 Python,MapReduce 实现复杂的查询逻辑的时候,开发难度相对较大,Hive 要比直接使用 MapReduce 开发效率更高。

开发效率更高原因是:

操作接口采用类似 SQL 的语法,提供快速开发的能力。

免去了写 MapReduce 的过程,减少开发人员的学习成本。

功能扩展方便

Hive 优缺点
  • 优点
    • 操作接口采用类似 SQL 的语法,提供快速开发的能力(简单、容易上手)。
    • 免去了写 MapReduce 的过程,减少开发人员的学习成本。
    • Hive 的执行延迟比较高,因此 Hive 常用于离线数据分析,对实时性要求不高的场合。
    • Hive 优势在于处理大数据,对于处理小数据没有优势,因为 Hive 的执行延迟比较高。
    • Hive 支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
    • 集群可自由拓展并且具有良好的容错性,节点出现问题 SQL 仍可完成执行。
  • 缺点
    • Hive 的 HQL 表达能力有限,当逻辑需求特别复杂的时候,还是要借助 MapReduce。
      • 迭代式算法无法表达
      • 数据挖掘方面不擅长
    • Hive 操作默认基于 MapReduce 引擎,而 MapReduce 引擎与其它的引擎(如 Spark 引擎)相比,特点就是慢、延 迟高、不适合交互式查询,所以 Hive 也有这个缺点(这里讲的是默认引擎,Hive 是可以更改成其他引擎的)。
    • Hive 自动生成的 MapReduce 作业,通常情况下不够智能化。
    • Hive 调优比较困难,粒度较粗。
Hive 应用场景
  • 日志分析:大部分互联网公司使用 Hive 进行日志分析,包括百度、淘宝等。
    • 统计网站一个时间段内的 PV、UV
    • 多维度数据分析
  • 海量结构化数据的离线分析

Hive 架构

1. Client (客户端)

Hive 允许 Client 连接的方式有三个 CLI(Hive Shell)、JDBC/ODBC(Java 访问 Hive)、WEBUI(浏览器访问 Hive)。 JDBC/ODBC 访问中间件 Thrift 软件框架,跨语言服务开发。DDL DQL DML,整体仿写一套 SQL 语句。

2. MetaStroe (元数据)

元数据,数据的数据。元数据包括表名、表结构信息、表所属的数据库(默认是 default 库)、表的拥有者(权限信 息)、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等。

元数据的存放一般需要借助于其他的数据载体(Derby 或 MySQL),默认存放在自带的 Derby 数据库(单用户局限性)中,推荐使用 MySQL 进行存储。连接数据库需要提供:uri、username、password、driver。

元数据服务的作用是:客户端连接 MetaStroe 服务,MetaStroe 服务再去连接 MySQL 数据库来存取元数据。有了 MetaStroe 服务,就可以有多个客户端同时连接,而且这些客户端不需要知道 MySQL 数据库的用户名和密码,只需要连接 MetaStroe 服务即可。

注:Hive 默认将元数据存储在 Derby 数据库中,但其仅支持单线程操作,若有一个用户在操作,其他用户则无法使用, 造成效率不高;而且当在切换目录后,重新进入 Hive 会找不到原来已经创建的数据库和表,因此一般使用 MySQL 数 据库存储元数据。

3. Driver

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

大致流程如下:

    • Parser:将 HQL 语句解析成抽象语法树(AST:Abstract Syntax Tree);
    • Semantic Analyzer:将抽象语法树编译成查询块;
    • Logic Plan Generator:将查询块转换成逻辑查询计划;
    • Logic Optimizer:重写逻辑查询计划,优化逻辑执行计划;
    • Physical Plan Gernerator:将逻辑计划转化成物理计划(MapReduce Jobs);
    • Physical Optimizer:选择最佳的 Join 策略,优化物理执行计划。最后执行。

4. HDFS

Hive 的数据存储在 HDFS 中,计算由 MapReduce 完成。HDFS 和 MapReduce 是源码级别上的整合,两者结合最佳。解释器、编译器、优化器完成 HQL 查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。

Hive 工作原理

当创建表的时候,需要指定 HDFS 文件路径,表和其文件路径会保存到 MetaStore,从而建立表和数据的映射关系。当数据加载入表时,根据映射获取到对应的 HDFS 路径,将数据导入。

用户输入 SQL 后,Hive 会将其转换成 MapReduce 或者 Spark 任务,提交到 YARN 上执行,执行成功将返回结果。

在搭建 Hive 数据仓库时,就会将 SQL 语句的常用指令操作,比如 SELECT、FROM、WHERE 以及函数等用 MapReduce 写成模板,并且将这些 MapReduce 模板封装到 Hive 中。

那我们所需要做的,就是根据业务需求编写相应的 SQL 语句,Hive 会自动的到封装好的 MapReduce 模板中去进行匹配。匹配完后将运行 MapReduce 程序,生成相应的分析结果,然后反馈给我们。总之就是做离线数据分析时,Hive 要比 直接使用 MapReduce 开发效率更高。

Hive 的启动与关闭
Hive 的启动 

检查 MySQL 服务是否启动。
[root@node01 ~]# systemctl status mysqld

启动 ZooKeeper(三台机器都需要执行)。
zkServer.sh start
zkServer.sh status

启动 HDFS + YARN。
[root@node01 ~]# start-all.sh

启动 JobHistory。
[root@node01 ~]# mapred --daemon start historyserver

初始化 hive 数据库(第一次启动时执行)。
[root@node01 ~]# schematool -dbType mysql -initSchema

启动 MetaStore 服务。
# 前台启动,学习期间推荐使用这种方式
[root@node01 ~]# hive --service metastore
# 后台启动
[root@node01 ~]# nohup hive --service metastore > /dev/null 2>&1 &

启动 HiveServer2 服务。
# 前台启动,学习期间推荐使用这种方式
[root@node01 ~]# hiveserver2
# 后台启动
[root@node01 ~]# nohup hiveserver2 > /dev/null 2>&1 &

客户端连接
客户端连接方式一。
[root@node03 ~]# hive
# 退出命令行命令:exit;

客户端连接方式二。
[root@node03 ~]# beeline -u jdbc:hive2://node01:10000 -n root
# 退出命令行命令:!exit

Hive 关闭

先关闭 HiveServer2 服务和 MetaStore 服务(前台启动的话直接 Ctrl + C 即可)。
再关闭 Hadoop 和 JobHistory。
[root@node01 ~]# stop-all.sh
[root@node01 ~]# mapred --daemon stop historyserver

再关闭 ZooKeeper(三台机器都需要执行)。
zkServer.sh stop
Hive 交互方式
[root@node03 ~]# beeline -u jdbc:hive2://node01:10000 -n root
jdbc:hive2://node01:10000> show databases;
Hive 的基本操作
1.创建数据库

CREATE DATABASE shop;

没有该数据库再创建
CREATE DATABASE IF NOT EXISTS crm;	

指定数据库创建的位置(数据库在 HDFS 上的存储路径)。
CREATE DATABASE IF NOT EXISTS school location '/hive/school.db';

2.修改数据库

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


3.数据库详情

显示所有数据库。
SHOW DATABASES;

可以通过 like 进行过滤。
SHOW DATABASES LIKE 's*';

查看某个数据库的详情。
DESC DATABASE school;

切换数据库。
USE school;

4.删除数据库

最简写法。
DROP DATABASE school;

如果删除的数据库不存在,最好使用 IF EXISTS 判断数据库是否存在。否则会报错: 
FAILED: SemanticException [Error 10072]: Database does not exist: school 。

DROP DATABASE IF EXISTS school;

如果数据库不为空,使用 CASCADE 命令进行强制删除。否则会报错: 
FAILED: Execution Error, return code
1 from org.apache.hadoop.hive.ql.exec.DDLTask. InvalidOperationException(message:Database
db_hive is not empty. One or more tables exist.)

DROP DATABASE IF EXISTS school CASCADE;
内外部表

1. 内部表

所谓内部表(managed table)即 Hive 管理的表,Hive 内部表的管理既包含逻辑以及语法上的,也包含实际物理意义上的,即创建 Hive 内部表时,数据将真实存在于表所在的目录内,删除内部表时,物理数据和文件也一并删除。默认创建的是内部表。

2. 外部表

外部表(external table)则不然,其管理仅仅只是在逻辑和语法意义上的,即新建表仅仅是指向一个外部目录而已。 同样,删除时也并不物理删除外部目录,而仅仅是将引用和定义删除。 一般情况下,在企业内部都是使用外部表的。因为会有多人操作数据仓库,可能会产生数据表误删除操作,为了数据安全性,通常会使用外部表,且方便达到数据共享。

Hive分区/分桶

分区针对的是数据的存储路径,分桶针对的是数据文件。

Hive 数据抽样

Hive提供了数据取样(SAMPLING)的功能,能够根据一定的规则进 行数据抽样,目前支持数据块抽样分桶抽样随机抽样

Hive 基本查询/高级查询
Hive 语句的执行顺序:
(7)    SELECT
(8)    DISTINCT <select_list>
(1)    FROM <left_table>
(3)    <join_type> JOIN <right_table>
(2)    ON <join_condition>
(4)    WHERE <where_condition>
(5)    GROUP BY <group_by_list>
(6)    HAVING <having_condition>
(9)    ORDER BY <order_by_condition>
(10)   LIMIT <limit_number>

FROM -> ON -> JOIN -> WHERE -> GROUP BY -> HAVING 
-> SELECT -> DISTINCT -> ORDER BY -> LIMIT

1. 一行变多行
EXPLODE() 可以将 Hive 一行中复杂的 Array 或者 Map 结构拆分成多行,那如何将某个列的数据转为数组呢?可以配
置 SPLIT 函数一起使用。

SELECT EXPLODE(SPLIT(types, "-")) FROM t_movie1;

+------+
| col  |
+------+
| 剧情   |
| 动作   |
| 犯罪   |
| 动作   |
| 冒险   |
| 剧情   |
| ...   |
+------+

如果我还想查看一下数组中这些电影类型隶属于哪个电影,需要配合侧视图 LATERAL VIEW 一起使用。

-- movie_type 是侧视图别名
SELECT id, name, type
FROM t_movie1,

-- 生成侧视图(表)AS 后面是侧视图的字段
LATERAL VIEW EXPLODE(SPLIT(types, "-")) movie_type AS type;
+-----+---------------+--------+
| id  |   name        | type   |
+-----+---------------+--------+
| 1   | 这个杀手不太冷  | 剧情    |
| 1   | 这个杀手不太冷  | 动作    |
| 1   | 这个杀手不太冷  | 犯罪    |
| 2   | 七武士         | 动作    |
| 2   | 七武士         | 冒险    |
| 2   | 七武士         | 剧情    |
| ... | ...           | ...    |
+-----+---------------+--------+

2. 多行变一行

COLLECT_SET() 和 COLLECT_LIST() 可以将多行数据转成一行数据,区别就是 LIST 的元素可重复而 SET 的元素是
去重的。

SELECT id, name,
CONCAT_WS(':', COLLECT_SET(type)) AS type_set,
CONCAT_WS(':', COLLECT_LIST(type)) AS type_list
FROM t_movie2
GROUP BY id, name;

+-----+----------+-----------------+-----------------+
| id  |   name   |   type_set     |   type_list    |
+-----+----------+-----------------+-----------------+
| 1   | 这个杀手不太冷  | 剧情:动作:犯罪        | 剧情:动作:犯罪        |
| 2   | 七武士      | 动作:冒险:剧情        | 动作:冒险:剧情        |
| 3   | 勇敢的心     | 动作:传记:剧情:历史:战争  | 动作:传记:剧情:历史:战争  |
| 4   | 东邪西毒     | 剧情:武侠:古装        | 剧情:剧情:剧情:武侠:古装  |
| 5   | 霍比特人     | 动作:奇幻:冒险        | 动作:奇幻:冒险        |
+-----+----------+-----------------+-----------------+


MySQL 实现方式: GROUP_CONCAT([DISTINCT] 要连接的字段 [ORDER BY 排序字段 ASC/DESC] [SEPARATOR
‘分隔符’])

窗口函数(开窗函数)

窗口函数,就是将聚合函数得出的数据变为原先的多行,相当于压缩和解压

窗口函数指的就是 OVER() 函数,其窗口是由一个 OVER 子句定义的多行记录。窗口函数一般分为三类:聚合型窗口函数分析型窗口函数以及取值型窗口函数

窗口函数语法:  

SELECT XX函数() OVER (PARTITION BY 用于分组的列 ORDER BY 用于排序的列 ROWS/RANGE BETWEEN 开始位置 AND 结
束位置);

PARTITION BY :后跟分组的字段,划分的范围被称为窗口
ORDER BY :决定窗口范围内数据的排序方式

移动窗口 :
	移动方向:
    CURRENT ROW :当前行
    PRECENDING :向当前行之前移动
    FOLLOWING :向当前行之后移动
    UNBOUNDED :起点或终点(一般结合 PRECEDING,FOLLOWING 使用)
      UNBOUNDED PRECEDING :表示该窗口第一行(起点)
      UNBOUNDED FOLLOWING :表示该窗口最后一行(终点)
	移动范围: ROWS 和 RANGE

    ROWS :	ROWS 后定义窗口从哪里开始(当前行也参与计算)ROWS 会根据 ORDER BY 子句排序后,按分组后排序
			列的顺序取前 N 行或后 N 行进行计算(当前行也参与计算)。
    	
			ROWS 2 PRECEDING :窗口从当前行的前两行开始计算,计算到当前行;
    	ROWS BETWEEN 2 PRECEDING AND CURRENT ROW :等同于上一句;
      ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING :窗口从当前行开始计算,计算到当前行的后两行;
      ROWS BETWEEN 2 PRECEDING AND 1 FOLLOWING :窗口从当前行的前两行开始计算,计算到当前行的下一
      行,当前行也参与计算;
      ROWS UNBOUNDED PRECEDING :窗口从第一行(起点)计算到当前行;
      ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW :等同于上一句;
      ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING :窗口从当前行计算到最后一行(终点);
      ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING :窗口从第一行(起点)计算到当前行下一行;
      ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING :窗口从第一行(起点)计算到最后一
      行(终点)。
  	
		RANGE :RANGE 后定义窗口从哪里开始(当前行也参与计算)RANGE 会根据 ORDER BY 子句排序后,按
			分组后排序列的值的整数区间取前 N 行或后 N 行进行计算(相同排序值的行都会被算进来,当前行也参与计算)。

    	整数区间解释:如果窗口范围子句为 RANGE BETWEEN 2 PRECEDING AND CURRENT ROW ,假设排序列的值为
        1 2 3 4 5 7 8 10,计算规则如下:
        1 => 1,因为前面没有任何行,所以只有自己
        2 => 1 + 2,因为前面只有一行,所以只加了 1
        3 => 1 + 2 + 3,前面两行加当前行
        4 => 2 + 3 + 4,前面两行加当前行
        5 => 3 + 4 + 5,前面两行加当前行
        7 => 5 + 6 + 7,因为 6 不存在,所以实际上只加了 5
        8 => 6 + 7 + 8,因为 6 不存在,所以实际上只加了 7
        11 => 8 + 9 + 11,因为 9 和 10 都不存在,所以实际上只有自己
    
		当 ORDER BY 缺少窗口范围子句时,窗口范围子句默认为: RANGE BETWEEN UNBOUNDED PRECEDING AND
    CURRENT ROW 。
    当 ORDER BY 和窗口范围子句都缺失时,窗口范围子句默认为: ROW BETWEEN UNBOUNDED PRECEDING AND
    UNBOUNDED FOLLOWING 。
聚合型窗口函数
	sum()
	max()
	min()
	count()
	avg()

分析型窗口函数
	RANK() :间断,相同值同序号,例如 1、2、2、2、5。
  DENSE_RANK() :不间断,相同值同序号,例如 1、2、2、2、3。
  ROW_NUMBER() :不间断,序号不重复,例如 1、2、3、4、5(2、3 可能是相同的值)。

取值型窗口函数
	LAG(COL, N, DEFAULT_VAL) :往前第 N 行数据,没有数据的话用 DEFAULT_VAL 代替。
  LEAD(COL, N, DEFAULT_VAL) :往后第 N 行数据,没有数据的话用 DEFAULT_VAL 代替。
  FIRST_VALUE(EXPR) :分组内第一个值,但是不是真正意义上的第一个,而是截至到当前行的第一个。
  LAST_VALUE(EXPR) :分组内最后一个值,但是不是真正意义上的最后一个,而是截至到当前行的最后一个。

Hive SQL 文件存储格式

STORED AS '文件格式'

常用的文件格式:

(1)TEXTFILE 默认格式 行存储
(2)SEQUENCEFILE 行存储 可分割 压缩;
(3)RCFILE 压缩快 快速列存取;
(4)ORCFILE(0.11以后出现) 压缩快 快速列存取 是rcfile的改良版本
(5)PARQUET 类似于orc,相对于orc文件格式,hadoop生态系统中大部分工程都支持parquet文件

说明:

其中TEXTFILE为默认格式,建表时不指定默认为这个格式,导入数据时会直接把数据文件拷贝到hdfs上不进行处理; SEQUENCEFILE,RCFILE,ORCFILE,PARQUET格式的表不能直接从本地文件导入数据,数据要先导入到textfile格式的表中, 然后再从表中用insert导入SequenceFile,RCFile,ORCFile,PARQUET各自表中;或者用复制表结构及数据的方式(create table as select * from table )。

一言以蔽之:如果为textfile的文件格式,直接load就OK,不需要走MapReduce;如果是其他的类型就需要走MapReduce了,因为其他的类型都涉及到了文件的压缩,这需要借助MapReduce的压缩方式来实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值