Hive 是一个基于 Hadoop 的数据仓库,可以将结构化的数据文件映射为一张数据库表,并提供简单的 SQL 查询功能,可以将 SQL 语句转换为 MapReduce 任务进行运行。其优点是学习成本低,可以通过类 SQL 语句快速实现简单的 MapReduce 统计,不必开发专门的 MapReduce 应用,十分适合数据仓库的统计分析。
数据仓库
概述
什么是数据仓库?
数据仓库(DataWarehouse)是用于报告和数据分析的系统,集成了一个或多个数据源的数据,为企业分析性报告和决策提供支持,主要通过离线计算进行数据分析。
数据仓库的特性?
- 主题导向(Subject-Oriented):数据仓库的数据模型设计,着重将数据按其意义归类至相同的主题区(subject area),因此称为主题导向。
- 集成性(Integrated):数据来自企业各 OLTP 系统,在数据仓库中是集成过且一致的。
- 时间差异性(Time-Variant):数据的变动,在数据仓库中是能够被纪录以及追踪变化的,有助于能反映出能随着时间变化的数据轨迹。
- 不变动性(Nonvolatile):数据一旦确认写入后是不会被取代或删除的,即使数据是错误的。
数据库与数据仓库的区别?
数据库与数据仓库的区别本质上是 OLTP 与 OLAP 的区别:
- OLTP:联机事务处理,处理一般即时性的作业数据,通常对少数记录进行查询、修改。用户较为关心操作的响应时间、数据的安全性、完整性和并发支持的用户数等问题。
- OLAP:联机分析处理,以多维度方式分析数据,多用于决策支持系统、数据仓库。
数据仓库,是在数据库已经大量存在的情况下,为了进一步挖掘数据资源、为了决策需要而产生的,而非“大型数据库”。
数据库 | 数据仓库 |
---|---|
面向事务 | 面向主题 |
存储业务数据 | 存储历史数据 |
避免数据冗余 | 允许数据冗余 |
为捕获数据而设计 | 为分析数据而设计 |
什么是元数据?有什么作用?
元数据(Meta Data),主要记录数据仓库中模型的定义、各层级间的映射关系、监控数据仓库的数据状态及ETL的任务运行状态。一般会通过元数据资料库(Metadata Repository)来统一地存储和管理元数据,其主要目的是使数据仓库的设计、部署、操作和管理能达成协同和一致。
元数据是数据仓库管理系统的重要组成部分,元数据管理是企业级数据仓库中的关键组件,贯穿数据仓库构建的整个过程,直接影响着数据仓库的构建、使用和维护。
- 构建数据仓库的主要步骤之一是 ETL。这时元数据将发挥重要的作用,它定义了源数据系统到数据仓库的映射、数据转换的规则、数据仓库的逻辑结构、数据更新的规则、数据导入历史记录以及装载周期等相关内容。数据抽取和转换的专家以及数据仓库管理员正是通过元数据高效地构建数据仓库。
- 用户在使用数据仓库时,通过元数据访问数据,明确数据项的含义以及定制报表。
- 数据仓库的规模及其复杂性离不开正确的元数据管理,包括增加或移除外部数据源,改变数据清洗方法,控制出错的查询以及安排备份等。
分层架构
数据仓库的数据来源于不同的源数据,并提供多样的数据应用,数据自下而上流入数据仓库后向上层开放应用,而数据仓库只是中间集成化数据管理的一个平台。按照数据流入流出的过程,数据仓库架构可分为三层:ODS层、DW层、APP层。
操作数据存储层(ODS):也叫贴源层。根据业务需求,此层数据可以直接存储不做任何更改的原始数据,也可以存储经过 ETL 去噪、去重、提脏后的数据。但无论如何,都是存储最细粒度的数据。
数据仓库层(DW):也称为细节层,是数据仓库的主体,从 ODS 层中获得的数据按照主题建立各种数据模型。比如按照事实表,维度表构建的星形模型、雪花模型等。
数据产品层(APP):为数据产品提供使用的结果数据。例如:前端应用直接读取的数据源;根据报表、专题分析需求而计算生成的数据。
数据仓库从各数据源获取数据及在数据仓库内的数据转换和流动都可以认为是 ETL(抽取 Extra, 转化 Transfer, 装载 Load)的过程。ETL 是数据仓库的流水线,也可以认为是数据仓库的血液,它维系着数据仓库中数据的新陈代谢,而数据仓库日常的管理和维护工作的大部分精力就是保持 ETL 的正常和稳定。
为什么要对数据仓库分层?
用空间换时间,通过大量的预处理来提升应用系统的用户体验(效率),因此数据仓库会存在大量冗余的数据;不分层的话,如果源业务系统的业务规则发生变化将会影响整个数据清洗过程,工作量巨大。
通过数据分层管理可以简化数据清洗的过程,因为把原来一步的工作分到了多个步骤去完成,相当于把一个复杂的工作拆成了多个简单的工作,每一层的处理逻辑都相对简单和容易理解,这样比较容易保证每一个步骤的正确性,当数据发生错误的时候,往往只需要局部调整某个步骤即可。
Hive
概述
什么是Hive?
Hive 是基于 Hadoop 的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类 SQL 查询功能。
为什么使用Hive?
直接使用 Hadoop 所面临的问题:
- 人员学习成本太高
- 项目周期要求太短
- MapReduce 实现复杂查询逻辑开发难度太大
使用 Hive 的好处:
- 操作接口采用类SQL语法,提供快速开发的能力
- 避免了去写 MapReduce,减少开发人员的学习成本
- 功能扩展方便
Hive有哪些特点?
可扩展:Hive 可以自由的扩展集群的规模,一般情况下不需要重启服务。
延展性:Hive 支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
容错:良好的容错性,节点出现问题SQL仍可完成执行。
Hive中的数据是如何存储的?
- Hive中所有的数据都存储在 HDFS 中,可支持
Text
,SequenceFile
,ParquetFile
,RCFILE
等存储格式。SequenceFile
是 Hadoop 中的一种文件格式,文件内容是以序列化的key-value
对象来组织的。 - 只需要在创建表的时候告诉 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 散列之后的多个文件。
架构
- 用户接口:包括 CLI、JDBC/ODBC 和 WebGUI。其中,CLI(Command Line Interface)为命令行;JDBC/ODBC 是 Hive 的 Java 实现,与传统数据库 JDBC 类似;WebGUI 是通过浏览器访问 Hive。
- 驱动:包括解析器、编译器、优化器和执行器。
- 解析器:将 SQL 字符串转换成抽象语法树 AST,一般用第三方工具库完成(如 Antlr);对 AST 进行语法分析,比如表是否存在、字段是否存在、SQL 语义是否有误。
- 编译器:将 AST 编译生成逻辑执行计划。
- 优化器:对逻辑执行计划进行优化。
- 执行器:把逻辑执行计划转换成可以执行的物理计划。对 Hive 来说就是 MapReduce。
- 元数据存储(Metastore):通常是存储在关系数据库如 MySQL/Derby 中。Hive 中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。
- 数据存储:Hive 的数据存储在 HDFS 中,大部分的查询、计算由 MapReduce 完成。
执行流程
- 通过用户接口提交 HQL 任务给驱动(Driver)。
- Driver 将 HQL 转化为抽象语法树(AST),然后转化为查询块(QB),再转化为逻辑查询计划,再转化为物理查询计划(得到 MapReduce 任务),优化 MapReduce 任务,生成执行计划,交给 ExecutionEngine 去执行。
- Driver 将任务提交给 JobTracker 或 ResourceManager 去执行,任务会读取 HDFS 中的文件并进行相应的操作,最终返回执行结果。
驱动(Driver)内部处理流程:
- 获取 Hive 元数据信息。编译器(Compiler)根据用户任务去元数据存储(Metastore)中获取需要的 Hive 元数据信息。
- 生成抽象语法树(AST)。Hive 使用 Antlr 实现 HQL 的词法和语法解析,将 HQL 转换为抽象语法树(Abstract Syntax Tree)。
- 生成查询块(QB)。对 AST 进一步抽象和结构化,得到查询的基本组成单元查询块(Query Block)。
- 生成逻辑执行计划。遍历 QB,将其翻译为操作树(Operator Tree),得到逻辑执行计划。Hive 最终生成的 MapReduce 任务,Map 阶段和 Reduce 阶段均由 Operator Tree 组成。逻辑操作符(Operator),就是在 Map 阶段或 Reduce 阶段完成单一特定的操作。
- 优化逻辑执行计划。逻辑计划优化器通过变换 Operator Tree,合并操作符,达到减少 MapReduce Job,减少 shuffle 数据量的目的。
- 生成物理执行计划。 将 Operator Tree 转化为 MapReduce Job,得到物理执行计划。
- 优化物理执行计划。物理层优化器进行 MapReduce Job 的变换,进行 MapJoin 等优化,生成最终的执行计划。
- 计划执行。将计划转交给 ExecutionEngine(执行引擎)去执行,提交给 JobTracker 或 Resource Manager 去执行。
安装
开发环境
- 三台虚拟机
1 | 192.168.153.100 node01 node01.hadoop.com |
- 目录结构
1 | /export/softwares:存放软件安装包 |
- 软件环境
1 | hadoop:hadoop-2.6.0-cdh5.14.0 |
安装
使用 node03 安装 Hive。
1 | cd /export/softwares |
Derby
使用 Derby 存储 Hive 的元数据。Derby 是 Apache 研发的开源数据库管理系统,是 Hive 内置的默认存储元数据的数据库。不推荐使用。
直接启动 ./hive
即可:
1 | # cd /export/servers/hive-1.1.0-cdh5.14.0/ |
退出后查看目录,这里注意两个目录:
- metastore_db:Derby 生成的存储元数据的数据库,在哪个目录执行
./hive
命令便在哪里产生一个metastore_db
数据库 。 - hcatalog:Hadoop 的表存储管理工具,它将 Hive Metastore 的表数据公开给其他应用程序,使得不同数据处理工具(MapReduce,Impala)能够轻松使用数据。
所以使用 Derby 的缺点也就暴露了出来:多个位置安装、执行./hive
后,产生多个元数据库,Hive 的库、表不统一。
MySQL
使用 MySQL 存储 Hive 的元数据。
- 复制一份
hive-env.sh
文件,添加 Hadoop 的环境变量
1 | cd /export/servers/hive-1.1.0-cdh5.14.0/conf |
1 | # Set HADOOP_HOME to point to a specific hadoop install directory |
- 修改
hive-site.xml
,注意填写正确的 MySQL 的登录验证信息
1 |
|
- 上传 MySQL 的驱动包,复制到 Hive 的
lib
目录下
1 | cp /export/softwares/mysql-connector-java-5.1.38.jar /export/servers/hive-1.1.0-cdh5.14.0/lib/ |
使用
Hive CLI
Hive CLI(Command Line Interface)为 Hive 的命令行接口,使用前需要启动 Metastore Server 服务:
1 | # 启动 Metastore Server 服务 |
Hive 配置项详见 **参数配置 **。在 Hive CLI 中使用 DDL/DML/DQL 详见 **HiveQL快速上手 **。
批处理
当 hive
命令使用 -e
或 -f
选项时,将以批处理模式执行 SQL:
1 | # 使用 -e 执行字符串中的 HQL |
交互式
如果 hive
命令没有使用 -e
和 -f
选项,它将进入交互式 shell 模式:
1 | $ ./hive |
Hive CLI 中使用 ;
作为命令结束的标识,使用 --
前缀作为注释。
执行Shell命令
在 Hive CLI 中可以执行简单的 bash shell 命令,只需要在命令前面加上 !
并以 ;
结尾即可:
1 | hive> !echo helloworld; |
在 Hive CLI 中不能使用需要用户进行输入的交互式命令,不支持自动补全、通配符和管道。
执行Hadoop命令
在 Hive CLI 中也可以执行 Hadoop 的 dfs
命令,无需输入前面的 hadoop
或 hdfs
,以 ;
结尾即可:
1 | hive> dfs -ls /; |
在 Hive CLI 执行 Hadoop 命令比在 Shell 中更高效,因为在 Shell 中执行时需要启动一个新的 JVM 实例,而 Hive CLI 会在同一个进程中执行。
命令行选项
使用 hive
命令时可以设置一些选项来执行 HQL 语句或文件并将结果打印到标准输出:
也可以在启动时设置 Hive 参数,仅对本次会话生效:
1 | # 使用 --hiveconf param=value 来设定参数 |
Beeline
Beeline 是一个基于 SQLLine 的 JDBC 客户端,使用前需要启动 HiveServer2 服务。
- 启动 Metastore Server 服务和 HiveServer2 服务:
1 | nohup ./hive --service metastore 2>&1 & |
- 启动 Beeline,连接 HiveServer2:
1 | # 启动 Beeline |
注意:Hive 的用户验证很弱,输入的 username
与 HDFS 中 hive
目录的 Owner
一致即可登录。
什么是 HiveServer2?
HiveServer2 提供 Hive 查询服务,客户端可以在不启动 CLI 的情况下对 Hive 中的数据进行操作,基于 Thrift(一种 RPC 协议)服务。相比 HiveServer 支持多客户端并发和身份认证,为 JDBC、ODBC 提供更好的支持。
从Hive1.0.0
开始,HiveServer 就已经不存在了,Hive CLI 使用的也是 HiveServer2 ,这对用户来说是透明的。
有了 Beeline 为什么还要保留 Hive CLI?
参考 **HIVE-10511 **。
Hive CLI 是一个遗留工具,有两个主要用途:一是作为 Hadoop 上 SQL 的胖客户端;二是作为 HiveServer1(原始的 Hive Server,现在通常称为“HiveServer1”)的命令行工具。
从Hive 1.0.0
开始,HiveServer1 已经被弃用并从 Hive 代码库中移除,并替换为 HiveServer2,因此第二个用途不再存在。对于第一个用途,Beeline 应该以与 Hive CLI 不同的实现方式提供相同的功能。
由于 Hive 社区长期以来建议使用 Beeline + HiveServer2 配置,因此理想情况下应该弃用 Hive CLI。但由于 Hive CLI 的广泛使用,我们改为在 Beeline 和 HiveServer2 之上用新的 Hive CLI 替换旧的 Hive CLI,以便 Hive 社区维护。这样,新的 Hive CLI 不管在 shell 脚本层面还是在高级代码层面都只是 Beeline 的别名。目标是使用 Hive CLI 时不需要对现有用户脚本进行更改或只需进行很少的更改。
但由于新的 Hive CLI 不支持旧的 Hive CLI 的某些功能,默认启用的仍是旧的 Hive CLI,可以使用以下命令进行指定使用新的 Hive CLI:
1 | export USE_DEPRECATED_CLI=false |
参数配置
Hive 参数有三种配置方式:配置文件、命令行参数和在 Hive CLI 中进行参数声明,配置优先级为参数声明 > 命令行参数 > 配置文件。
配置文件
使用 Cloudera Manager 方式安装的 Hive 的配置文件存放在 /etc/hive/conf/
下。用户自定义的配置文件 hive-site.xml
会覆盖掉默认配置文件 hive-default.xml
,也会覆盖掉 Hadoop 的配置。配置文件对本机启动的所有 Hive 进程生效。
数据库目录位置
Hive 数据库在 HDFS 的存放位置可以通过配置 hive-site.xml
指定:
1 | <property> |
显示数据库和字段名称
Hive CLI 中当前数据库名称,以及查询结果中字段的显示,可以通过配置 hive-site.xml
开启:
1 | <property> |
开启前后对比:
1 | -- 开启前 |
Fetch抓取
Fetch 抓取是指,Hive 对某些情况的查询可以不使用 MapReduce 计算,例如:全表查询。在这种情况下,Hive可以读取表对应存储目录下的文件,然后输出查询结果到控制台。
Fetch 级别可以在 hive-site.xml
中修改,对于 CDH 6.1.1 来说,Hive 的 Fetch 级别默认为 minimal
:
1 | <property> |
运行日志信息
Hive 中的日志分为两种:
- 系统日志,记录了 Hive 的运行情况,错误状况。
- Job 日志,记录了 Hive 中 Job 的历史执行过程。
Hive 的系统日志默认存放在 /tmp/root/hive.log
中,可以通过配置 log4j.properties
修改日志文件的存放位置:
1 | /tmp/${user.name} = |
命令行参数
启动 Hive 时可以在使用 --hiveconf
选项来配置 Hive 参数,或者添加 --conf confpath
载入新配置文件,仅对本次会话生效:
1 | # 使用 --hiveconf 选项配置 hive 参数 |
注:--hiveconf
及变体 -hiveconf
都可以用来配置 Hive 参数。
参数声明
在 Hive CLI 中可以使用 set
查询和设定参数,仅对本次会话生效:
1 | -- 查询所有参数 |
使用DBeaver
除了在服务器上通过 Hive CLI 连接,开发过程中还可以使用 DBeaver 数据库工具进行连接。
中文元数据乱码
Hive 表的描述信息,在 Hive CLI 中显示正常,但在 DBeaver 中为乱码。DBeaver连接hive中文注释乱码
编辑 MySQL 配置文件:
/etc/my.cnf 1
2
3
4+ init_connect='SET collation_connection = utf8_unicode_ci'
+ init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_general_ci重启
mysqld
服务:1
$ systemctl restart mysqld
指定 Hive 元数据表的字段字符集为 UTF8:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20$ mysql -uroot -p
mysql> use metastore;
mysql> select * from COLUMNS_V2 limit 2;
+-------+---------+-------------+-----------+-------------+
| CD_ID | COMMENT | COLUMN_NAME | TYPE_NAME | INTEGER_IDX |
+-------+---------+-------------+-----------+-------------+
| 182 | ??? | phonenumber | string | 0 |
| 182 | ??? | status_code | string | 1 |
+-------+---------+-------------+-----------+-------------+
# 修改字段和表注解
mysql> alter table COLUMNS_V2 modify column COMMENT varchar(256) character set utf8;
mysql> alter table TABLE_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;
# 修改分区字段注解
mysql> alter table PARTITION_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;
mysql> alter table PARTITION_KEYS modify column PKEY_COMMENT varchar(4000) character set utf8;
#修改索引注解
mysql> alter table INDEX_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;删除之前的表,重新创建。
参考资料
Replacing the Implementation of Hive CLI Using Beeline
Hive SQL的编译过程
Hive新版本工作原理详解——不要在看老版本的工作原理了