Loading

18-Hive入门&安装

1. Hive 概述

1.1 什么是 Hive?

Apache Hive 是一款建立在 Hadoop 之上的开源数据仓库工具,可以将存储在 Hadoop 文件中的结构化、半结构化数据文件映射为一张数据库表,基于表提供了一种类似 SQL 的查询模型,称为 Hive 查询语言(HQL),用于访问和分析存储在 Hadoop 文件中的大型数据集。

Hive 核心是将 HQL 转换为 MapReduce 程序,然后将程序提交到 Hadoop 群集执行。Hive 由 Facebook 实现并开源。

1.2 为什么使用 Hive?

使用 Hadoop MapReduce 直接处理数据所面临的问题:

  • 人员学习成本太高,需要掌握 Java 语言
  • MapReduce 实现复杂查询逻辑开发难度太大。

使用 Hive 处理数据的好处:

  • 操作接口采用类 SQL 语法,提供快速开发的能力(简单、容易上手);
  • 避免直接写 MapReduce,减少开发人员的学习成本;
  • 支持自定义函数,功能扩展很方便;
  • 背靠 Hadoop,擅长存储分析海量数据集。

1.3 Hive 与 Hadoop 的关系

从功能来说,数据仓库软件,至少需要具备下述两种能力:

  1. 存储数据的能力
  2. 分析数据的能力

Apache Hive 作为一款大数据时代的数据仓库软件,当然也具备上述两种能力。

只不过 Hive 并不是自己实现了上述两种能力,而是借助 Hadoop。Hive 利用 HDFS 存储数据,利用 MapReduce 查询分析数据。

这样突然发现 Hive 没啥用,不过是套壳 Hadoop 罢了。其实不然,Hive 的最大的魅力在于用户专注于编写 HQL,Hive 帮你转换成为 MapReduce 程序完成对数据的分析。

1.4 模拟实现 Hive 功能

a. 场景需求

在 HDFS 文件系统上有一个文件,路径为 /data/china_user.txt,其内容如下:

1,zhangsan,18,beijing
2,lisi,25,shanghai
3,allen,30,shanghai
4,wangwu,15,nanjing
5,james,45,hangzhou
6,tony,26,beijing

需求:统计来自于上海年龄大于 25 岁的用户有多少个?

如果让你设计 Hive 这款软件,要求能够实现用户编写 sql 语句,Hive 自动将 sql 转换 MapReduce 程序,处理位于 HDFS 上的结构化数据。如何实现?


重点理解下面两点:

  1. Hive 能将数据文件映射成为一张表,这个“映射”是指什么?
  2. Hive 软件本身到底承担了什么功能职责?

b. 功能实现关键

(1)映射信息记录

映射在数学上称之为一种对应关系,比如 y=x+1,对于每一个 x 的值都有与之对应的 y 的值。在 Hive 中能够写 sql 处理的前提是针对表,而不是针对文件,因此需要将文件和表之间的对应关系描述记录清楚。映射信息的专业叫法是“元数据信息”(元数据是指用来描述数据的数据 metadata)。

具体来看,要记录的元数据信息包括:

  • 表对应着哪个文件(位置信息)
  • 表的列对应着文件哪一个字段(顺序信息)
  • 文件字段之间的分隔符是什么

(2)sql 语法解析、编译

用户写完 sql 之后,Hive 需要针对 sql 进行语法校验,并且根据记录的元数据信息解读 sql 背后的含义,制定执行计划。并且把执行计划转换成 MapReduce 程序来执行,把执行的结果封装返回给用户。


回答上边的两个问题:

  1. Hive 能将数据文件映射成为一张表,这个“映射”是指什么?=> 文件和表之间的对应关系
  2. Hive 软件本身到底承担了什么功能职责?=> 将 HQL(Hive SQL)转化成 MapReduce 程序

c. 最终效果

基于上述分析,最终要想模拟实现的 Hive 的功能,大致需要下图所示组件参与其中,从中可以感受一下 Hive 承担了什么职责。

2. Hive 组件

  • 用户接口】包括 CLI、JDBC/ODBC、WebGUI。其中,CLI(Command Line Interface)为 Shell 命令行;Hive 中的 Thrift 服务器允许外部客户端通过网络与 Hive 进行交互,类似于 JDBC 或 ODBC 协议。WebGUI 是通过浏览器访问 Hive。
  • 元数据存储】通常是存储在关系数据库如 MySQL/Derby 中。Hive 中的元数据包括表的名字、表的列和分区及其属性、表的属性(是否为外部表等)、表的数据所在目录等。
  • Driver 驱动程序(包括语法解析器、计划编译器、优化器、执行器)】完成 HQL 查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在 HDFS 中,并在随后有执行引擎调用执行。
  • 执行引擎】Hive 本身并不直接处理数据文件,而是通过执行引擎处理。当下 Hive 支持 MapReduce、Tez、Spark3 种执行引擎。

3. Hive 数据模型

【数据模型】用来描述数据、组织数据和对数据进行操作,是对现实世界数据特征的描述。

Hive 的数据模型类似于 RDBMS 库表结构,此外还有自己特有模型。Hive 中的数据可以在粒度级别上分为 3 类:

  1. Table 表
  2. Partition 分区
  3. Bucket 分桶

3.1 Databases

Hive 作为一个数据仓库,在结构上积极向传统数据库看齐,也分数据库(Schema),每个数据库下面有各自的表组成。默认数据库 default。

Hive 的数据都是存储在 HDFS 上的,默认有一个根目录,在 hive-site.xml 中,由参数 hive.metastore.warehouse.dir 指定。默认值为 /user/hive/warehouse。

因此,Hive 中的数据库在 HDFS 上的存储路径为:${hive.metastore.warehouse.dir}/databasename.db

比如,名为 tree 的数据库存储路径为:/user/hive/warehouse/tree.db。

3.2 Tables

Hive 表与关系数据库中的表相同。Hive 中的表所对应的数据是存储在 Hadoop 的文件系统中,而表相关的元数据是存储在 RDBMS 中。

在 Hadoop 中,数据通常驻留在 HDFS 中,尽管它可以驻留在任何 Hadoop 文件系统中,包括本地文件系统或 S3。

Hive 有两种类型的表。创建表时,默认是内部表。关于内部表和外部表的区别,后续再做展开探讨。

  • Managed Table 内部表、托管表
  • External Table 外部表

Hive 中的表的数据在 HDFS 上的存储路径为:${hive.metastore.warehouse.dir}/databasename.db/tablename

比如,itcast 的数据库下 t_user 表存储路径为:/user/hive/warehouse/itcast.db/t_user

3.3 Partitions

Partition 分区是 Hive 的一种优化手段表。分区是指根据分区列(例如“日期 day”)的值将表划分为不同分区。这样可以更快地对指定分区数据进行查询。

分区在存储层面上的表现是:table 表目录下以子文件夹形式存在。

一个子文件夹表示一个分区。子文件命名标准:分区列=分区值

Hive 还支持分区下继续创建分区,即所谓的“多重分区”。

3.4 Buckets

Bucket 分桶表是 Hive 的一种优化手段表。分桶是指根据表中字段(例如“编号ID”)的值经过 hash 计算规则将数据文件划分成指定的若干个小文件。

【分桶规则】hashFunc(ID) % 桶个数,余数相同的分到同一个文件。

【分桶好处】可以优化 join 查询和方便抽样查询。Bucket 分桶表在 HDFS 中表现为同一个表目录下数据根据 hash 散列之后变成多个文件。

4. Hive 安装部署

4.1 Hive 元数据

Metadata 即元数据。元数据包含用 Hive 创建的 database、table、表的位置、类型、属性、字段顺序类型等元信息。元数据存储在关系型数据库中。如 Hive 内置的 Derby 或第三方如 MySQL 等。

Metastore 即元数据服务。Metastore 服务的作用是管理 Metadata 元数据,对外暴露服务地址,让各种客户端通过连接 Metastore 服务,由 Metastore 再去连接 MySQL 数据库来存取元数据。

有了 Metastore 服务,就可以有多个客户端同时连接,而且这些客户端不需要知道 MySQL 数据库的用户名和密码,只需要连接 Metastore 服务即可。某种程度上也保证了 Hive 元数据的安全。

Metastore 服务配置有 3 种模式:内嵌模式本地模式远程模式。区分 3 种配置方式的关键是弄清楚两个问题:

  1. Metastore 服务是否需要单独配置、单独启动?
  2. Metadata 是存储在内置的 Derby 中,还是第三方 RDBMS,比如 MySQL。

安装前准备

由于 Apache Hive 是一款基于 Hadoop 的数据仓库软件,通常部署运行在 Linux 系统之上。因此不管使用何种方式配置 Hive Metastore,必须要先保证服务器的基础环境正常,Hadoop 集群健康可用。

Hive 不是分布式安装运行的软件,其分布式的特性主要借由 Hadoop 完成。包括分布式存储、分布式计算。

启动 Hive 之前必须先启动 Hadoop 集群。特别要注意,需等待 HDFS 安全模式关闭之后再启动运行 Hive。

因为 Hive 需要把数据存储在 HDFS 上,并通过 MapReduce 作为执行引擎处理数据,因此需要在 Hadoop 中添加相关配置属性,以满足 Hive 在 Hadoop 上运行。需修改 Hadoop 的 core-site.xml,并且 Hadoop 集群同步配置文件,重启生效。

<!-- 配置所有节点的liujiaqi用户都可作为代理用户 -->
<property>
  <name>hadoop.proxyuser.liujiaqi.hosts</name>
  <value>*</value>
</property>
<!-- 配置liujiaqi用户能够代理的用户组为任意组 -->
<property>
  <name>hadoop.proxyuser.liujiaqi.groups</name>
  <value>*</value>
</property>
<!--配置liujiaqi用户能够代理的用户为任意用户-->
<property>
  <name>hadoop.proxyuser.liujiaqi.users</name>
  <value>*</value>
</property>

至于为什么要加这些配置,在下面安装 HiveServer2 的时候会说到。

a. 内嵌模式

内嵌模式(Embedded Metastore)是 Metastore 默认部署模式。此种模式下,元数据存储在内置的 Derby 数据库,并且 Derby 数据库和 Metastore 服务都嵌入在主 HiveServer 进程中,当启动 HiveServer 进程时,Derby 和 Metastore 都会启动。不需要额外起 Metastore 服务。

【缺点】一次只能支持一个活动用户,适用于测试体验,不适用于生产环境。

安装流程:

# 1. 上传解压安装包
cd /opt
tar -zxvf /opt/software/apache-hive-3.1.2-bin.tar.gz -C /opt/module/
cd /opt/module
mv apache-hive-3.1.2-bin hive

# 2. 解决 Hadoop、Hive 之间 Guava 版本差异
cd /opt/module/hive
rm -rf lib/guava-19.0.jar
cp /opt/module/hadoop-3.1.3/share/hadoop/common/lib/guava-27.0-jre.jar ./lib/

# 3. 修改 Hive 环境变量文件: 添加 HADOOP_HOME
cd /opt/module/hive/conf/
mv hive-env.sh.template hive-env.sh
vim hive-env.sh
export HADOOP_HOME=/opt/module/hadoop-3.1.3
export HIVE_CONF_DIR=/opt/module/hive/conf
export HIVE_AUX_JARS_PATH=/opt/module/hive/lib

# 4. 初始化 Metadata
cd /opt/module/hive
bin/schematool -dbType derby -initSchema

# 5. 启动 Hive 服务
bin/hive

内嵌模式下,判断是否初始化成功的依据是执行命令之后输出信息和执行命令的当前路径下是否有文件产生。会在初始化命令执行目录生成 derby.log 和 metastore_db:

Hive 默认使用的元数据库为 Derby。Derby 数据库的特点是同一时间只允许一个客户端访问。如果多个 Hive 客户端同时访问,就会报错。由于在企业开发中,都是多人协作开发,需要多客户端同时访问 Hive,怎么解决呢?我们可以将 Hive 的元数据改为用 MySQL 存储,MySQL 支持多客户端同时访问。

先把 Hive 恢复到测试内嵌模式之前的样子:删除安装目录下的 derby.log 和 metastore_db,顺便将 HDFS 上 /user/hive/warehouse 目录下的内容删除。

b. 本地模式

本地模式(Local Metastore)下,Metastore 服务与主 HiveServer 进程在同一进程中运行,但是存储元数据的数据库在单独的进程中运行,并且可以在单独的主机上。Metastore 服务将通过 JDBC 与 Metastore 数据库进行通信。

本地模式采用外部数据库来存储元数据,推荐使用 MySQL。

Hive 根据 hive.metastore.uris 参数值来判断,如果为空,则为本地模式。

【缺点】每启动一次 Hive 服务,都内置启动了一个 Metastore。

安装流程:

# 1. 上传解压安装包
cd /opt
tar -zxvf /opt/software/apache-hive-3.1.2-bin.tar.gz -C /opt/module/
cd /opt/module
mv apache-hive-3.1.2-bin hive

# 2. 解决 Hadoop、Hive 之间 Guava 版本差异
cd /opt/module/hive
rm -rf lib/guava-19.0.jar
cp /opt/module/hadoop-3.1.3/share/hadoop/common/lib/guava-27.0-jre.jar ./lib/

# 3. 修改 Hive 环境变量文件: 添加 HADOOP_HOME
cd /opt/module/hive/conf/
mv hive-env.sh.template hive-env.sh
vim hive-env.sh
export HADOOP_HOME=/opt/module/hadoop-3.1.3
export HIVE_CONF_DIR=/opt/module/hive/conf
export HIVE_AUX_JARS_PATH=/opt/module/hive/lib

# 4. 添加 mysqlJDBC 驱动到 Hive 的 lib 目录下
mv ~/mysql-connector-java-8.0.16.jar lib/

# 5. 新增 hive-site.xml:配置 mysql 等相关信息
vim hive-site.xml

# 6. 初始化 Metadata(初始化成功会在 mysql 中创建 74 张表)
cd /opt/module/hive
bin/schematool -initSchema -dbType mysql -verbos

# 7. 启动 Hive 服务
bin/hive

hive-site.xml

<configuration>
    <!-- 存储元数据mysql相关配置 -->
    <property>
        <name>javax.jdo.option.ConnectionURL</name>
        <value>jdbc:mysql://node1:3306/hive?createDatabaseIfNotExist=true&amp;useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;allowPublicKeyRetrieval=true</value>
    </property>

    <property>
        <name>javax.jdo.option.ConnectionDriverName</name>
        <value>com.mysql.jdbc.Driver</value>
    </property>

    <property>
        <name>javax.jdo.option.ConnectionUserName</name>
        <value>root</value>
    </property>

    <property>
        <name>javax.jdo.option.ConnectionPassword</name>
        <value>123456</value>
    </property>

    <!-- 关闭元数据存储授权  -->
    <property>
        <name>hive.metastore.event.db.notification.api.auth</name>
        <value>false</value>
    </property>

    <!-- 关闭元数据存储版本的验证 -->
    <property>
        <name>hive.metastore.schema.verification</name>
        <value>false</value>
    </property>
</configuration>

c. 远程模式

远程模式(Remote Metastore)下,Metastore 服务在其自己的单独 JVM 上运行,而不在 HiveServer 的 JVM 中运行。如果其他进程希望与 Metastore 服务器通信,则可以使用 Thrift Network API 进行通信。

在生产环境中,建议用远程模式来配置 Hive Metastore。在这种情况下,其他依赖 Hive 的软件都可以通过 Metastore 访问 Hive。由于还可以完全屏蔽数据库层,因此这也带来了更好的可管理性/安全性。

远程模式下,需要配置 hive.metastore.uris 参数来指定 Metastore 服务运行的机器 IP 和端口,并且需要单独手动启动 Metastore 服务。

安装流程同本地模式,这里只给出 hive-site.xml。

<configuration>

    <!-- 远程模式 Metastore 服务地址 -->
    <property>
        <name>hive.metastore.uris</name>
        <value>thrift://node1:9083</value>
    </property>
  
    <!-- hiveserver2 运行绑定 Host -->
    <property>
        <name>hive.server2.thrift.bind.host</name>
        <value>node1</value>
    </property>

      <!-- hiveserver2 运行绑定 Port -->
    <property>
        <name>hive.server2.thrift.port</name>
        <value>10000</value>
    </property>

    <!-- 关闭元数据存储授权 -->
    <property>
        <name>hive.metastore.event.db.notification.api.auth</name>
        <value>false</value>
    </property>

    <!-- 关闭元数据存储版本的验证 -->
    <property>
        <name>hive.metastore.schema.verification</name>
        <value>false</value>
    </property>
</configuration>

如果在远程模式下,直接运行 Hive 服务,在执行操作的时候会报错,错误信息如下:

因为在远程模式下,Metastore 服务和 HiveServer 是两个单独的进程了,必须首先启动 Hive Metastore 服务才可以使用 Hive:

$ cd /opt/module/hive

# 前台启动
$ ./bin/hive --service metastore

# 后台启动(关闭使用jps + kill)输入命令回车执行 再次回车 进程将挂起后台
$ nohup ./bin/hive --service metastore &

# 前台启动 & 开启debug日志
$ ./bin/hive --service metastore --hiveconf hive.root.logger=DEBUG,console

4.2 Hive 客户端

a. CLI 工具

Hive 发展至今,总共历经了两代客户端工具。

  • 第一代客户端(deprecated 不推荐使用)
    • $HIVE_HOME/bin/hive 是一个 shellUtil
    • 主要功能:(1)可用于以交互或批处理模式运行 Hive 查询;(2)用于 Hive 相关服务的启动,比如 Metastore 服务。
  • 第二代客户端(recommended 推荐使用)
    • $HIVE_HOME/bin/beeline 是一个 JDBC 客户端,是官方强烈推荐使用的 Hive 命令行工具,和第一代客户端相比,性能加强安全性提高。
    • Beeline Shell 在「嵌入式模式」和「远程模式」下均可工作。在嵌入式模式下,它运行嵌入式 Hive(类似于 Hive Client),而远程模式下 Beeline 通过 Thrift 连接到单独的 HiveServer2 服务上,这也是官方推荐在生产环境中使用的模式。

那么问题来了,HiveServer2 是什么?HiveServer1 哪里去了?

b. HiveServer/2

HiveServer、HiveServer2 都是 Hive 自带的两种服务,允许客户端在不启动 CLI 的情况下对 Hive 中的数据进行操作,且两个都允许远程客户端使用多种编程语言如 Java、Python 等向 Hive 提交请求,取回结果。

但是,HiveServer 不能处理多于一个客户端的并发请求,因此在 Hive-0.11.0 版本中重写了 HiveServer 代码得到了 HiveServer2,进而解决了该问题。故 HiveServer 已被废弃。HiveServer2 支持多客户端的并发和身份认证,旨在为开放 API 客户端如 JDBC、ODBC 提供更好的支持。

用户说明

在远程访问 Hive 数据时,客户端并未直接访问 Hadoop 集群,而是由 Hivesever2 代理访问。由于 Hadoop 集群中的数据具备访问权限控制,所以此时需考虑一个问题:访问 Hadoop 集群的用户身份是谁?

是 Hiveserver2 的启动用户?还是客户端的登录用户?答案是都有可能,具体是谁,由 Hiveserver2 的 hive.server2.enable.doAs 参数决定,该参数的含义是是否启用 Hiveserver2 用户模拟的功能。

若启用,则 Hiveserver2 会模拟成客户端的登录用户去访问 Hadoop 集群的数据;不启用,则 Hivesever2 会直接使用启动用户访问 Hadoop 集群数据。该功能默认开启。

生产环境,推荐开启用户模拟功能,因为开启后才能保证各用户之间的权限隔离。


Hivesever2 的模拟用户功能,依赖于 Hadoop 提供的 proxy user(代理用户功能),只有 Hadoop 中的代理用户才能模拟其他用户的身份访问 Hadoop 集群。因此,需要将 Hiveserver2 的启动用户设置为 Hadoop 的代理用户。

  1. 在 core-site.xml 中新增如下配置,并将文件分发给集群中的其他节点(然后重启 Hadoop 集群);

    <!-- 配置所有节点的liujiaqi用户都可作为代理用户 -->
    <property>
      <name>hadoop.proxyuser.liujiaqi.hosts</name>
      <value>*</value>
    </property>
    <!-- 配置liujiaqi用户能够代理的用户组为任意组 -->
    <property>
      <name>hadoop.proxyuser.liujiaqi.groups</name>
      <value>*</value>
    </property>
    <!--配置liujiaqi用户能够代理的用户为任意用户-->
    <property>
      <name>hadoop.proxyuser.liujiaqi.users</name>
      <value>*</value>
    </property>
    
  2. 在 hive-site.xml 中添加如下配置信息

    <!-- hiveserver2 运行绑定 Host -->
    <property>
        <name>hive.server2.thrift.bind.host</name>
        <value>node1</value>
    </property>
    
      <!-- hiveserver2 运行绑定 Port -->
    <property>
        <name>hive.server2.thrift.port</name>
        <value>10000</value>
    </property>
    
  3. 启动 hiveserver2:hive --service hiveserver2

c. 组件关系梳理

HiveServer2 通过 Metastore 服务读写元数据。所以在远程模式下,启动 HiveServer2 之前必须先首先启动 Metastore 服务。

特别注意!远程模式下,Beeline 客户端只能通过 HiveServer2 服务访问 Hive。而 Hive Client 是通过 Metastore 服务访问的。具体关系如下:

在 Hive 运行的服务器上,首先启动 Metastore 服务,然后启动 HiveServer2 服务。

# nohup     放在命令开头,表示不挂起,也就是关闭终端进程也继续保持运行状态
# /dev/null 是Linux文件系统中的一个文件,被称为黑洞,所有写入该文件的内容都会被自动丢弃
# 2>&1      0-标准输入、1-标准输出、2-错误输出,'>'左边不写默认就是'1','2>&1'表示将错误重定向到标准输出上
# &         放在命令结尾,表示后台运行
### nohup bin/hiveserver2 1>/dev/null &
### nohup bin/hiveserver2 >/dev/null &
### nohup bin/hiveserver2 1>/dev/null 2>/dev/null &
### nohup bin/hiveserver2 >/dev/null 2>&1&

# 一般会组合使用:nohup [命令操作] >file 2>&1 &,表示将xxx命令运行的标准数据结果输出到file中,2同1,并保持命令启动的进程在后台运行。
$ nohup /opt/module/hive/bin/hive --service metastore &
$ nohup /opt/module/hive/bin/hive --service hiveserver2 &

为了方便使用,可以直接编写脚本来管理服务的启动和关闭:

#!/bin/bash

HIVE_LOG_DIR=$HIVE_HOME/logs
if [ ! -d $HIVE_LOG_DIR ]
then
    mkdir -p $HIVE_LOG_DIR
fi

# 检查进程是否运行正常,参数1为进程名,参数2为进程端口
function check_process()
{
    pid=$(ps -ef 2>/dev/null | grep -v grep | grep -i $1 | awk '{print $2}')
    ppid=$(netstat -nltp 2>/dev/null | grep $2 | awk '{print $7}' | cut -d '/' -f 1)
    echo $pid
    [[ "$pid" =~ "$ppid" ]] && [ "$ppid" ] && return 0 || return 1
}

function hive_start()
{
    metapid=$(check_process HiveMetastore 9083)
    cmd="nohup hive --service metastore >$HIVE_LOG_DIR/metastore.log 2>&1 &"
    [ -z "$metapid" ] && eval $cmd || echo "Metastroe服务已启动"
    server2pid=$(check_process HiveServer2 10000)
    cmd="nohup hive --service hiveserver2 >$HIVE_LOG_DIR/hiveServer2.log 2>&1 &"
    [ -z "$server2pid" ] && eval $cmd || echo "HiveServer2服务已启动"
}

function hive_stop()
{
    metapid=$(check_process HiveMetastore 9083)
    [ "$metapid" ] && kill $metapid || echo "Metastore服务未启动"
    server2pid=$(check_process HiveServer2 10000)
    [ "$server2pid" ] && kill $server2pid || echo "HiveServer2服务未启动"
}

case $1 in
"start")
    hive_start
    ;;
"stop")
    hive_stop
    ;;
"restart")
    hive_stop
    sleep 2
    hive_start
    ;;
"status")
    check_process HiveMetastore 9083 >/dev/null && echo "Metastore服务运行正常" || echo "Metastore服务运行异常"
    check_process HiveServer2 10000 >/dev/null && echo "HiveServer2服务运行正常" || echo "HiveServer2服务运行异常"
    ;;
*)
    echo Invalid Args!
    echo 'Usage: '$(basename $0)' start|stop|restart|status'
    ;;
esac

使用 jps -ml 命令查看运行情况:

d. CLI-hive 使用

在 $HIVE_HOME/bin/hive 是一个 ShellUtil,通常称之为 Hive 的第一代客户端或者旧客户端,主要功能有两个:

  1. 交互式或批处理模式运行 Hive 查询(注意,此时作为客户端,需要并且能够访问的是 Hive Metastore 服务,而不是 HiveServer2 服务)
  2. Hive 相关服务的启动(比如 Metastore、HiveServer2 服务)

可以通过运行 hive -Hhive --help 来查看命令行选项。

-e <quoted-query-string>          -- 执行命令行 -e 参数后指定的sql语句 运行完退出
-f <filename>                     -- 执行命令行 -f 参数后指定的sql文件 运行完退出
-H,--help                         -- 打印帮助信息
   --hiveconf <property=value>    -- 设置参数
-S,--silent                       -- 静默模式
-v,--verbose                      -- 详细模式,将执行 sql 回显到 console
   --service service_name         -- 启动 Hive 的相关服务

【提示】如果您是远程模式部署,请手动启动运行 Metastore 服务。如果是内嵌模式和本地模式,直接运行 bin/hive,Metastore 服务会内嵌一起启动。

可以直接在启动 Hive Metastore 服务的机器上使用 bin/hive 客户端操作,此时不需要进行任何配置。

# 远程模式 首先启动 Metastore 服务
$ ./bin/hive --service metastore
# 克隆会话窗口 使用 hive client 连接
$ ./bin/hive

配置 CLI 客户端流程:

# 1. 上传解压安装包
cd /opt
tar -zxvf /opt/software/apache-hive-3.1.2-bin.tar.gz -C /opt/module/
cd /opt/module
mv apache-hive-3.1.2-bin hive

# 2. 解决 Hadoop、Hive 之间 Guava 版本差异
cd /opt/module/hive
rm -rf lib/guava-19.0.jar
cp /opt/module/hadoop-3.1.3/share/hadoop/common/lib/guava-27.0-jre.jar ./lib/

# 3. 修改 Hive 环境变量文件: 添加 HADOOP_HOME
cd /opt/module/hive/conf/
mv hive-env.sh.template hive-env.sh
vim hive-env.sh
export HADOOP_HOME=/opt/module/hadoop-3.1.3
export HIVE_CONF_DIR=/opt/module/hive/conf
export HIVE_AUX_JARS_PATH=/opt/module/hive/lib

# 4. 添加 Metastore 服务地址
vim hive-site.xml

<configuration>
  <property>
      <name>hive.metastore.uris</name>
      <value>thrift://node1:9083</value>
  </property>
</configuration>

如果需要在其他机器上通过 bin/hive 或 hiveserver2 访问 Hive Metastore 服务,只需要在该机器的 hive-site.xml 配置中添加 Metastore 服务地址即可。

【补充】如果 hive-site.xml 中同时配置了javax.jdo.option.Connection* 配置和 hive.metastore.uris,此时 Hive CLI 会优先使用 hive.metastore.uris

(1)Batch Mode 批处理模式

当使用 -e-f 选项运行 bin/hive 时,它将以批处理模式执行 SQL 命令。所谓的批处理可以理解为一次性执行,执行完毕退出

# -e
$HIVE_HOME/bin/hive -e 'show databases'

# -f
# 编辑一个sql文件 里面写上合法正确的sql语句
cd ~
vim hive.sql
show databases;
# 执行 从客户端所在机器的本地磁盘加载文件
$HIVE_HOME/bin/hive -f /root/hive.sql
# 也可以从其他文件系统加载sql文件执行
$HIVE_HOME/bin/hive -f hdfs://<namenode>:<port>/hive-script.sql
$HIVE_HOME/bin/hive -f s3://mys3bucket/s3-script.sql
# 使用静默模式将数据从查询中转储到文件中
$HIVE_HOME/bin/hive -S -e 'select * from itheima.student' > a.txt

(2)Interactive Shell 交互式模式

所谓交互式模式可以理解为客户端和 Hive 服务一直保持连接,除非手动退出客户端。

/export/server/hive/bin/hive

hive> show databases;
OK
default
itcast
itheima
Time taken: 0.028 seconds, Fetched: 3 row(s)

hive> use itcast;
OK
Time taken: 0.027 seconds

hive> exit;

(3)启动 Hive 服务

比如 Metastore 服务和 HiveServer2 服务的启动。

# --service
$HIVE_HOME/bin/hive --service metastore
$HIVE_HOME/bin/hive --service hiveserver2

# --hiveconf
$HIVE_HOME/bin/hive --hiveconf hive.root.logger=DEBUG,console

e. CLI-beeline 使用

Hive 经过发展,推出了第二代客户端 Beeline,但是 Beeline 客户端不是直接访问 Metastore 服务的,而是需要单独启动 hiveserver2 服务。

$HIVE_HOME/bin/beeline 被称之为第二代客户端或者新客户端,是一个 JDBC 客户端,是官方强烈推荐使用的 Hive 命令行工具。和第一代客户端相比,性能加强安全性提高。Beeline 在嵌入式模式和远程模式下均可工作。

Beeline 支持的参数非常多,可以通过官方文档进行查询:https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients#HiveServer2Clients-Beeline–NewCommandLineShell

在嵌入式模式下,它运行嵌入式 Hive(类似于 Hive CLI);远程模式下 Beeline 通过 Thrift 连接到单独的 HiveServer2 服务上,这也是官方推荐在生产环境中使用的模式。

# 在 Hive 运行的服务器上,首先启动 Metastore 服务,然后启动 HiveServer2 服务。
$ nohup /opt/module/hive/bin/hive --service metastore &
$ nohup /opt/module/hive/bin/hive --service hiveserver2 &

在 node3 上使用 beeline 客户端进行连接访问。需要注意 hiveserver2 服务启动之后需要稍等一会才可以对外提供服务。

Beeline 是 JDBC 的客户端,通过 JDBC 协议和 hiveserver2 服务进行通信,协议地址:jdbc:hive2://node1:10000

$ /opt/module/hive/bin/beeline
Beeline version 3.1.2 by Apache Hive
beeline> ! connect jdbc:hive2://node1:10000
Connecting to jdbc:hive2://node1:10000
Enter username for jdbc:hive2://node1:10000: root
Enter password for jdbc:hive2://node1:10000: 
Connected to: Apache Hive (version 3.1.2)
Driver: Hive JDBC (version 3.1.2)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://node1:10000> 

【补充】如果不进行那个 Hadoop#core-site.xml 的配置,连接过程中出现的问题:

就将一开始配置的 hadoop.proxyuser.xxx.hosts 和 hadoop.proxyuser.xxx.groups 中的 xxx 设置为错误日志中显示的 User:xxx)。* 表示可通过超级代理 xxx 操作 Hadoop 的用户、用户组和主机。

主要原因是 Hadoop 引入了一个安全伪装机制,使得 Hadoop 不允许上层系统直接将实际用户传递到 Hadoop 层,而是将实际用户传递给一个超级代理 xxx,由此代理在 Hadoop 上执行操作,避免任意客户端随意操作 Hadoop,如下图:

图上的超级代理是“Oozie”,你自己的超级代理是上面设置的“xxx”。而 Hadoop 内部还是延用 Linux 对应的用户和权限。即你用哪个 Linux 用户启动 Hadoop,对应的用户也就成为 Hadoop 的内部用户。

5. 使用扩展

5.1 常用交互命令

$ bin/hive -help
usage: hive
 -d,--define <key=value>          Variable subsitution to apply to hive
                                  commands. e.g. -d A=B or --define A=B
    --database <databasename>     Specify the database to use
 -e <quoted-query-string>         SQL from command line
 -f <filename>                      SQL from files
 -H,--help                        Print help information
    --hiveconf <property=value>   Use value for given property
    --hivevar <key=value>         Variable subsitution to apply to hive
                                  commands. e.g. --hivevar A=B
 -i <filename>                    Initialization SQL file
 -S,--silent                      Silent mode in interactive shell
 -v,--verbose                     Verbose mode (echo executed SQL to the console)

(1)-e 不进入 Hive 的交互窗口执行 HQL 语句

$ bin/hive -e "select id from student;"

(2)-f 执行脚本中的 HQL 语句

$ bin/hive -f hive.sql  > hive_result.txt

5.2 属性配置方式

Hive 作为一款复杂的数据仓库软件,除了一些默认的属性行为之外,还支持用户配置属性进行修改,使得在某些场景下满足用户的需求。

作为用户我们需要掌握两件事:

  1. Hive 有哪些属性支持修改,修改了有什么功能;
  2. Hive 支持哪种方式进行修改,修改是临时生效还是永久生效的。

查看当前所有的配置信息:

hive> set;

Hive 配置属性的规范列表是在 HiveConf.Java 类中管理的,因此请参考该 HiveConf.java 文件,以获取 Hive 当前使用的发行版中可用的配置属性的完整列表。从 Hive 0.14.0 开始,会从 HiveConf.java 类中直接生成配置模板文件 hive-default.xml.template,它是当前版本配置及其默认值的可靠来源。

详细的配置参数大全可以参考Hive官网配置参数,在页面使用 ctrl+f 进行搜索:https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties

(1)hive-site.xml

在 $HIVE_HOME/conf 路径下,可以添加一个 hive-site.xml 文件,把需要定义修改的配置属性添加进去,这个配置文件会影响到这个 Hive 安装包的任何一种服务启动、客户端使用方式,可以理解为是 Hive 的全局配置。

比如我们指定使用 MySQL 作为 Hive 元数据的存储介质,那么就需要把 Hive 连接 MySQL 的相关属性配置在 hive-site.xml 文件中,这样不管是本地模式还是远程模式启动,不管客户端本地连接还是远程连接,都将访问同一个元数据存储介质,大家使用的元数据都是一致的。

(2)hiveconf 命令行参数

hiveconf 是一个命令行的参数,用于在使用 Hive CLI 或 Beeline CLI 的时候指定配置参数。这种方式的配置在整个的会话 session 中有效,会话结束则失效。

比如在启动 Hive 服务的时候,为了更好的查看启动详情,可以在命令行添加 -hiveconf param=value 来设定参数修改日志级别:

# 仅对本次 Hive 启动有效
$ bin/hive --hiveconf hive.root.logger=DEBUG,console

查看参数设置:

hive> set mapreduce.job.reduces;

(3)set 命令

在 Hive CLI 或 Beeline 中使用 set 命令为 set 命令之后的所有 SQL 语句设置配置参数,这个也是会话级别的。

这种方式也是用户日常开发中使用最多的一种配置参数方式。因为 Hive 倡导一种:谁需要、谁配置、谁使用的一种思想,避免你的属性修改影响其他用户的修改。

-- 启用 Hive 动态分区,需要在 Hive 会话中设置两个参数
hive> set hive.exec.dynamic.partition=true;
hive> set hive.exec.dynamic.partition.mode=nonstrict;

(4)服务器特定的配置文件

您可以设置特定 Metastore 的配置值在 hivemetastore-site.xml 中,还可以把 HiveServer2 特定的配置值放在 hiveserver2-site.xml 中。

  • Metastore 服务会读取 $HIVE_CONF_DIR 或类路径中可用的 hive-site.xml 以及 hivemetastore-site.xml 配置文件。
  • HiveServer2 读取 $HIVE_CONF_DIR 或类路径中可用的 hive-site.xml 以及 hiveserver2-site.xml。如果 HiveServer2 以嵌入式模式使用元存储,则还将加载 hivemetastore-site.xml。

小结

上述设定方式的优先级依次递增。即 配置文件 < 命令行参数 < 参数声明

从 Hive 0.14.0 开始,会从 HiveConf.java 类中直接生成配置模板文件 hive-default.xml.template,它是当前版本配置变量及其默认值的可靠来源。hive-default.xml.template 位于安装根目录下的 conf 目录中,并且 hive-site.xml 也应在同一目录中创建。

可以使用 SHOW CONF 命令显示有关配置变量的信息。

配置方式的优先级顺序,优先级依次递增:hive-site.xml 文件 < hiveconf 参数 < set 设置。set 参数声明会覆盖命令行参数 hiveconf,hiveconf 会覆盖配置文件 hive-site.xml 设定。

日常开发使用中,如果不是核心的需要全局修改的参数属性,建议使用 set 命令进行设置。另外,Hive 也会读入 Hadoop 的配置,因为 Hive 是作为 Hadoop 的客户端启动的,所以如果有冲突的配置,Hive 的配置也会覆盖 Hadoop 的配置。

注意某些系统级的参数,例如 log4j 相关的设定,必须用前两种方式设定,因为那些参数的读取在会话建立以前已经完成了。

5.3 常见属性配置

a. 客户端显示当前库和表头

(1)在 hive-site.xml 中加入如下两个配置

<property>
    <name>hive.cli.print.header</name>
    <value>true</value>
    <description>Whether to print the names of the columns in query output.</description>
</property>
<property>
    <name>hive.cli.print.current.db</name>
    <value>true</value>
    <description>Whether to include the current database in the Hive prompt.</description>
</property>

(2)HiveCLI 在运行时可以显示当前使用的库和表头信息

b. 运行日志路径配置

(1)Hive 的 log 默认存放在 /tmp/当前系统用户名/hive.log 目录下

(2)修改 Hive 的 log 存放日志到 /opt/module/hive/logs 下:

  1. 修改 $HIVE_HOME/conf 下的 hive-log4j2.properties.template 文件名称为 hive-log4j2.properties
  2. 在 hive-log4j2.properties 文件中修改 log 存放位置:property.hive.log.dir=/opt/module/hive/logs

c. Hive 的 JVM 堆内存设置

新版本的 Hive 启动的时候,默认申请的 JVM 堆内存大小为 256M,JVM 堆内存申请的太小,导致后期开启本地模式,执行复杂的 SQL 时经常会报错:java.lang.OutOfMemoryError: Java heap space,因此最好提前调整一下 HADOOP_HEAPSIZE 这个参数。

(1)修改 $HIVE_HOME/conf 下 的 hive-env.sh.template 为 hive-env.sh

(2)将 hive-env.sh 中的参数 export HADOOP_HEAPSIZE 修改为 4096,重启 Hive。

d. 关闭 Hadoop 虚拟内存检查

在 yarn-site.xml 中关闭虚拟内存检查(如果已经关闭了就不需要配了)。

(1)修改前记得先停掉 Hadoop

(2)在 yarn-site.xml 添加如下配置

<property>
    <name>yarn.nodemanager.vmem-check-enabled</name>
    <value>false</value>
</property>

(3)修改完后记得分发 yarn-site.xml,并重启 YARN。

6. Hive 初体验

6.1 Hive - MySQL

对于初次接触 Apache Hive 的人来说,最大的疑惑就是:Hive 从数据模型看起来和关系型数据库 MySQL 等好像。包括 Hive SQL 也是一种类 SQL 语言。那么实际使用起来如何?

体验步骤:按照 MySQL 的思维,在 Hive 中创建、切换数据库,创建表并执行插入数据操作,最后查询是否插入成功。

-- 创建数据库
create database itcast;
-- 列出所有数据库
show databases;
-- 切换数据库
use itcast;

-- 建表
create table t_student(id int, name varchar(255));
-- 插入一条数据
insert into table t_student values(1, "allen");
-- 查询表数据
select * from t_student;

在执行插入数据的时候,发现插入速度极慢,sql 执行时间很长,为什么?

最终插入一条数据,历时 30s 的时间。

首先登陆 Hadoop YARN 上观察是否有 MapReduce 任务执行痕迹。

YARN Web UI:http://resourcemanager_host:8088/

然后登陆 Hadoop HDFS 浏览文件系统,根据 Hive 的数据模型,表的数据最终是存储在 HDFS 和表对应的文件夹下的。

HDFS Web UI:http://namenode_host:9870/

【小结】Hive 虽然具有 RDBMS 数据库的外表,包括数据模型、SQL 语法都十分相似,但应用场景却完全不同。Hive 只适合用来做海量数据的离线分析。Hive 的定位是数据仓库,面向分析的 OLAP 系统。因此时刻告诉自己,Hive 不是大型数据库,也不是要取代 MySQL 承担业务数据处理。

  • Hive SQL 语法和标准 SQL 很类似,使得学习成本降低不少。
  • Hive 底层是通过 MapReduce 执行的数据插入动作,所以速度慢。
  • 如果大数据集这么一条一条插入的话是非常不现实的,成本极高。
  • Hive 应该具有自己特有的数据插入表方式,结构化文件映射成为表。

6.2 结构化数据映射成为表

在 Hive 中,使用 insert+values 语句插入数据,底层是通过 MapReduce 执行的,效率十分低下。此时回到 Hive 的本质上:可以将结构化的数据文件映射成为一张表,并提供基于表的 SQL 查询分析。

假如现在有一份结构化的数据文件,如何才能映射成功呢?在映射成功的过程中需要注意哪些问题?不妨猜想文件的存储路径?字段类型?字段顺序?字段之间的分隔符问题?

在 HDFS 根目录下创建一个结构化数据文件 user.txt,里面内容如下:

1,zhangsan,18,beijing
2,lisi,25,shanghai
3,allen,30,shanghai
4,woon,15,nanjing
5,james,45,hangzhou
6,tony,26,beijing

在 Hive 中创建一张表 t_user(字段的类型顺序要和文件中字段保持一致):

create table t_user(id int, name varchar(255), age int, city varchar(255));

执行数据查询操作,发现表中并没有数据。

【猜想】难道数据文件要放置在表对应的 HDFS 路径下才可以成功?

再次执行查询操作,显示如下,都是 null,

表感知到结构化文件的存在了!但是并没有正确识别文件中的数据。

【猜想】还需要指定文件中字段之间的分隔符?重建张新表,指定分隔符。

-- 建表语句增加分隔符指定语句
create table t_user_1(id int, name varchar(255), age int, city varchar(255))
row format delimited
fields terminated by ',';

-- 把 user.txt 文件从本地文件系统上传到 hdfs
$ hadoop fs -put user.txt /user/hive/warehouse/itcast.db/t_user_1/

-- 执行查询操作
select * from t_user_1;

可以正确识别数据了:

【猜想】此时再创建一张表,保存分隔符语法,但是故意使得字段类型和文件中不一致。还能不能正常识别数据?

-- 建表语句增加分隔符指定语句
create table t_user_2(id int,name int,age varchar(255),city varchar(255))
row format delimited
fields terminated by ',';

-- 把 user.txt 文件从本地文件系统上传到 hdfs
$ hadoop fs -put user.txt /user/hive/warehouse/itcast.db/t_user_2/

-- 执行查询操作
select * from t_user_2;

此时发现,有的列显示 null,有的列显示正常:

name 字段本身是字符串,但是建表的时候指定 int,类型转换不成功;age 是数值类型,建表指定字符串类型,可以转换成功。说明 Hive 中具有自带的类型转换功能,但是不一定保证转换成功。

【小结】要想在 Hive 中创建表跟结构化文件映射成功,需要注意以下几个方面问题:

  • 创建表时,字段顺序、字段类型要和文件中保持一致。
  • 如果类型不一致,Hive 会尝试转换,但是不保证转换成功。不成功显示 null。
  • 文件好像要放置在 Hive 表对应的 HDFS 目录下,其他路径可以吗?
  • 建表的时候好像要根据文件内容指定分隔符,不指定可以吗?
posted @ 2023-07-29 22:03  tree6x7  阅读(78)  评论(0编辑  收藏  举报