Hive 基本介绍

2022-06-21 warehouse

Hive 是由 Facebook 开发建立在 Hadoop 之上的数据仓库,初衷是为了减少复杂 MR 程序的编写工作,其本身不存储和处理数据,依赖 HDFS 存储数据和 MR 处理数据,有类 SQL 语言的 HiveQL,其不完全支持 SQL 标准,例如不支持更新、索引、事务,子查询和连接操作也有很多限制。

简介

数仓存储的是静态数据,Hive 会把 HQL 语句转换为 MR 进行批处理,同时还提供了一系列 ETL 相关的工具,可以便于处理 HDFS 上保存的数据。Hive 可以在某些列上构建索引,加速一些查询操作,创建的索引会保存在另外的表中。

简单来说,Hive 将元数据保存在关系型数据库中,数据保存在 HDFS 上,然后可以通过 Hive 的命令行 beeline 链接 Hive 集群,并将 HQL 通过 MapReduce 运行。

开源安装

可以直接从 Hive Download 下载对应的二进制文件。

----- 解压软件包并移动到 /opt/module/hive 目录下
# tar -zxvf apache-hive-3.1.2-bin.tar.gz
----- 下载MySQL的驱动,保存到 /opt/module/hive/lib 目录下
# wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.28/mysql-connector-java-8.0.28.jar

----- 创建Hive的的相关配置文件
# vim /opt/module/hive/conf/hive-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://127.0.0.1:3306/hivedb?createDatabaseIfNotExist=true&amp;characterEncoding=UTF-8&amp;useSSL=false</value>
  </property>
  <property>
    <name>javax.jdo.option.ConnectionDriverName</name>
    <value>com.mysql.cj.jdbc.Driver</value>
  </property>
  <property>
    <name>javax.jdo.option.ConnectionUserName</name>
    <value>root</value>
  </property>
  <property>
    <name>javax.jdo.option.ConnectionPassword</name>
    <value>5Kk,boZpAUp6</value>
  </property>
  <property>
    <name>hive.metastore.schema.verification</name>
    <value>false</value>
  </property>
  <property>
    <name>hive.metastore.warehouse.dir</name>
    <value>/hive</value>
  </property>
  <property>
    <name>hive.server2.thrift.port</name>
    <value>10000</value>
  </property>
  <property>
    <name>hive.server2.webui.port</name>
    <value>10002</value>
  </property>
</configuration>

----- 然后初始化元数据库,执行完成后可以登录数据库查看
# schematool -initSchema -dbType mysql

实际初始化数据库会执行 scripts/metastore/upgrade 目录下的 SQL 文件,例如 mysql/hive-schema-3.1.0.mysql.sql 文件。

启动服务

支持的服务可以通过 hive --help 命令查看,或者 hive --service metastore --help 方式启动,这里主要是介绍 MetaStore 和 HiveServer2 的启动,通过如下命令启动,不过是前台运行,这里通过 systemd 进行维护。

hive --service metastore
hive --service hiveserver2

----- 可以通过systemd维护
# vim /etc/systemd/system/hive-metastore.service
[Unit]
Description=Hive MetaStore
Requires=network-online.target
After=network-online.target

[Service]
EnvironmentFile=/etc/sysconfig/warehouse
User=root
ExecStart=/opt/module/hive/bin/hive --service metastore

[Install]
WantedBy=multi-user.target

# vim /etc/systemd/system/hive-server.service
[Unit]
Description=Hive Server
Requires=network-online.target
After=network-online.target

[Service]
EnvironmentFile=/etc/sysconfig/warehouse
User=root
ExecStart=/opt/module/hive/bin/hive --service hiveserver2

[Install]
WantedBy=multi-user.target

----- 然后重新加载并启动服务
# systemctl daemon-reload
# systemctl stop hive-metastore
# systemctl start hive-metastore
# systemctl stop hive-server
# systemctl start hive-server

注意,HiveServer 无法支持并发的客户端处理,而 HiveServer2 除了支持并发外,还支持身份认证、Web页面等。然后可以链接 10002 端口。

客户端

通过客户端可以启动服务,执行 SQL 等,一种是老的 Hive 方式,还可以使用 Beeline 方式,推荐后者。

----- 执行Hive客户端命令,链接的是Hive Server地址,如果使用了 tmux 可能需要 export TERM=xterm
beeline -u jdbc:hive2://127.0.0.1:10000 -n root
beeline> ! connect jdbc:hive2://127.0.0.1:10000
这里是 HiveServer2 的服务端口。

su - omm
----- 确认主管理节点,然后登录
sh ${BIGDATA_HOME}/om-server/om/sbin/status-oms.sh
----- 加载客户端相关的环境变量
source /opt/Bigdata/client/bigdata_env

----- 创建、切换、查看数据库,默认使用default数据库
beeline> CREATE DATABASE test;
beeline> USE test;
beeline> SELECT current_database();
----- 创建并写入表
beeline> CREATE TABLE user_info(id STRING, name STRING, gender STRING, age INT, addr STRING);
beeline> INSERT INTO user_info(id, name, gender, age, addr) VALUES("12005000201", "A", "男", 19, "A城市");
----- 查看表结构,可以通过 extended 查看详细信息,以及表参数更加美观输出
beeline> DESC user_info;
beeline> DESC extended user_info;
beeline> DESC formatted user_info;
----- 或者本地加载数据
beeline> LOAD DATA LOCAL INPATH "/tmp/user.txt" INTO TABLE user_info;

可以通过如下方式创建外表。

# cat /tmp/user.csv
10000,2017-10-01,北京,20,0,0.123456e-60
----- 这里保存在HDFS上面
# hdfs dfs -mkdir /hive/user_info
beeline> CREATE EXTERNAL TABLE user_info(
    id STRING,
    name STRING,
    gender STRING,
    age INT,
    addr STRING
)
PARTITIONED BY(year STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
STORED AS TEXTFILE LOCATION '/hive/user_info';
beeline> INSERT INTO user_info PARTITION(year="2018") VALUES("12005000201", "A", "男", 19, "A城市");
beeline> LOAD DATA LOCAL INPATH "/tmp/user.csv" INTO TABLE user_info PARTITION(year="2018");
# hdfs dfs -ls /hive/user_info
# hdfs dfs -cat /hive/user_info/year=2018/000000_0

如下是常见操作。

----- 修改列属性
ALTER TABLE user_info CHANGE name named STRING AFTER id;
----- 增加列
ALTER TABLE user_info ADD COLUMNS (city STRING);

Metastore

数据库、表、函数等 Hive 对象的定义存储在 Metastore 中,根据系统的配置方式,统计数据和授权记录也可能存储在那里,然后 Hive 和其它执行引擎在运行时会使用该数据来确定如何解析、授权和有效执行用户查询。

监听端口默认使用 9083 端口,详见 hive.metastore.port 配置端口,默认配置详见 conf/hive-default.xml.template 模板配置文件。

其它

安全集群

----- 创建一个Principal
# kadmin -proot/admin -w'Mrs@2022' -q"addprinc -randkey hive/package"
----- 生成所需的Keytab文件
# kadmin -proot/admin -w'Mrs@2022' -q"ktadd -k /opt/module/keys/hive.keytab hive/package"
# kinit -kt /opt/module/keys/hive.keytab hive/package@EXAMPLE.COM
----- 使用Beeline远程访问Hive
# beeline -u "jdbc:hive2://127.0.0.1:10000/default;principal=hive/package@EXAMPLE.COM"

----- 修改 Hive 的配置文件,增加如下 Kerberos 相关的配置项,重启 HiveServer2 和 MetaStore 服务,可以使用 _HOST 表示当前主机
# vim /opt/module/hive/conf/hive-site.xml
<property>
   <name>hive.server2.authentication</name>
   <value>kerberos</value>
</property>
<property>
   <name>hive.server2.authentication.kerberos.principal</name>
   <value>hive/Package@EXAMPLE.COM</value>
</property>
<property>
   <name>hive.server2.authentication.kerberos.keytab</name>
   <value>/opt/module/keys/hive.keytab</value>
</property>

<property>
   <name>hive.metastore.sasl.enabled</name>
   <value>true</value>
</property>
<property>
   <name>hive.metastore.kerberos.principal</name>
   <value>hive/Package@EXAMPLE.COM</value>
</property>
<property>
   <name>hive.metastore.kerberos.keytab.file</name>
   <value>/opt/module/keys/hive.keytab</value>
</property>
----- 修改 Hadoop 的配置文件,增加如下配置项,然后重启 dfs 和 yarn 服务
# vim /opt/module/hadoop/etc/hadoop/core-site.xml
<property>
    <name>hadoop.proxyuser.hive.hosts</name>
    <value>*</value>
</property>
<property>
    <name>hadoop.proxyuser.hive.groups</name>
    <value>*</value>
</property>
<property>
    <name>hadoop.proxyuser.hive.users</name>
    <value>*</value>
</property>

常用示例

>>>>> CSV
CREATE TABLE user_info_csv(
    id STRING,
    name STRING,
    gender STRING,
    age INT,
    addr STRING
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
STORED AS TEXTFILE
LOCATION "obs://mrs-doris-obs/user_info_csv";
INSERT INTO user_info_csv VALUES("12005000201", "A", "男", 19, "A城市");
INSERT INTO user_info_csv VALUES("12005000501", "B", "男", 18, "B城市");

>>>>> Parquet
CREATE TABLE user_info_parquet(
    id STRING,
    name STRING,
    gender STRING,
    age INT,
    addr STRING
)
STORED AS PARQUET
LOCATION "obs://mrs-doris-obs/user_info_parquet"
TBLPROPERTIES('parquet.compression'='SNAPPY');
INSERT INTO user_info_parquet VALUES("12005000201", "A", "男", 19, "A城市");
INSERT INTO user_info_parquet VALUES("12005000501", "B", "男", 18, "B城市");

>>>>> ORC
CREATE TABLE user_info_orc(
    id STRING,
    name STRING,
    gender STRING,
    age INT,
    addr STRING
)
STORED AS ORC
LOCATION "obs://mrs-doris-obs/user_info_orc"
TBLPROPERTIES('orc.compression'='SNAPPY');
INSERT INTO user_info_orc VALUES("12005000201", "A", "男", 19, "A城市");
INSERT INTO user_info_orc VALUES("12005000501", "B", "男", 18, "B城市");

>>>>> CSV分区表
CREATE TABLE user_info_part(
    id STRING,
    name STRING,
    gender STRING,
    age INT,
    addr STRING
)
PARTITIONED BY(year STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
STORED AS TEXTFILE
LOCATION "obs://mrs-doris-obs/user_info_part";
INSERT INTO user_info_part PARTITION(year="2018") VALUES("12005000201", "A", "男", 19, "A城市");
SHOW PARTITIONS user_info_part;

>>>>> CSV二级分区表
CREATE TABLE user_info_part_two(
    id STRING,
    name STRING,
    gender STRING,
    age INT,
    addr STRING
)
PARTITIONED BY(year STRING, day STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
STORED AS TEXTFILE
LOCATION "obs://mrs-doris-obs/user_info_part_two";
INSERT INTO user_info_part_two PARTITION(year="2018",day="12") VALUES("12005000201", "A", "男", 19, "A城市");
SHOW PARTITIONS user_info_part_two;

常见问题

开启日志

日志默认保存在 /tmp/hive/hive.log 文件中,其中第二层的目录为启动用户名,可以通过如下方式修改。

# vim ${HIVE_HOME}/conf/hive-log4j2.properties
property.hive.log.dir = /root/app/hive/log

不允许使用root

默认是不允许 root 登录的,会报 root is not allowed to impersonate anonymous 的错误,需要修改 Hadoop 的配置文件 core-site.xml 增加如下配置项,然后重启服务。

<property>
  <name>hadoop.proxyuser.root.hosts</name>
  <value>*</value>
</property>
<property>
  <name>hadoop.proxyuser.root.groups</name>
  <value>*</value>
</property>

不允许创建文件

一般会报 org.apache.hadoop.security.AccessControlException Permission denied: user=anonymous, access=WRITE, inode="/":root:supergroup:drwxr-xr-x 错误,此时可以通过如下方式关闭安全模式,如果权限不足则授予权限。

hadoop dfsadmin -safemode leave
hdfs dfsadmin -safemode leave
hadoop fs -chmod 777 /

其它

使用 beeline 时可能会报 Failed to construct terminal; falling back to unsupported 错误,主要是终端的配置问题,只需要添加 export TERM=xterm-color 环境变量即可。