Hive 数据仓库技术全解(一):环境搭建、服务配置与核心DDL/DML/DQL基础

作者:Lijingang
日期:2026-07-10
标签:Hive Hadoop 大数据 SQL MapReduce


前言

在大数据生态体系中,Apache Hive 扮演着至关重要的角色。它是构建在 Hadoop 之上的数据仓库工具,能将结构化数据映射为一张张表,并提供类 SQL(HQL)的查询能力。Hive 的核心价值在于:将 HQL 语句翻译为 MapReduce 任务,在 YARN 上执行,数据在 HDFS 上读写(当前生产环境常将执行引擎切换为 Tez 或 Spark 以提升性能,本文先以底层原理最通用的 MapReduce 进行解析。),从而让不懂 Java MapReduce 编程的开发者也能轻松处理海量数据。

本文将从环境搭建、架构原理、HQL 基础语法,系统性地梳理 Hive 技术栈,助你全面掌握这个大数据利器。

本文为《Hive数据仓库技术全解》系列的第一篇,聚焦于环境搭建、服务配置、DDL(库表操作)和基础DML/DQL语法。后续文章预告:

第二篇:HQL高级函数(窗口函数、UDF/UDAF/UDTF、炸裂函数与行列转换,分区/分桶)

第三篇:企业级生产调优(聚合优化、数据倾斜优化、小文件合并、join优化等)
—**

一、Hive 环境搭建

1.1 安装 Hive 框架

<>符号表示根据自己的安装情况自行配置

第一步,下载并安装 Hive 框架,配置环境变量。

#java环境变量
export JAVA_HOME=/<java安装路径>
export PATH=$PATH:$JAVA_HOME/bin

#hadoop环境变量
export HADOOP_HOME=/<hadoop安装路径>
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

# hive
export HIVE_HOME=/<hive安装路径>
export PATH=$PATH:$HIVE_HOME/bin

1.2 配置 Hive 与 Hadoop 关联

Hive 需要与 Hadoop 协同工作 —— 将 SQL 翻译成 MapReduce 程序在 YARN 上运行,数据也在 HDFS 上读取和保存。核心配置如下:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
    <!-- 配置 Hive 在 HDFS 中的工作目录 -->
    <property>
        <name>hive.metastore.warehouse.dir</name>
        <value>/user/hive/warehouse</value>
    </property>

    <!-- JDBC 连接的 URL -->
    <property>
        <name>javax.jdo.option.ConnectionURL</name>
        <value>jdbc:mysql://<ip地址>:<端口>/metastore?useSSL=false</value>
    </property>

    <!-- MySQL 驱动类 -->
    <property>
        <name>javax.jdo.option.ConnectionDriverName</name>
        <value>com.mysql.jdbc.Driver</value>
    </property>

    <!-- MySQL 连接的用户名 -->
    <property>
        <name>javax.jdo.option.ConnectionUserName</name>
        <value>root</value>
    </property>
</configuration>

1.3 元数据存储 —— 对接 MySQL

Hive 自带的 Derby 数据库只适合本地测试,生产环境中需要将元数据存储在 MySQL 中。关键步骤如下:

  • 在 Linux 上安装 MySQL,使用临时密码登录并修改密码
  • 执行元数据库初始化命令:
schematool -dbType mysql -initSchema -verbose
  • 将 MySQL 驱动 jar 包放入 Hive 的 lib 目录下

二、Hive 工作流程

Hive 将 SQL 语句翻译为 MR 任务交给 YARN 执行,并在 HDFS 上读写文件,同时还负责保存 HDFS 文件的元数据。这套机制极大提升了开发效率 —— 开发者只需写 SQL,Hive 负责将其高效地转换为分布式计算任务。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

核心流程可概括为:

用户提交 HQL → Driver 解析 SQL → Compiler 生成执行计划
→ Optimizer 优化 → Executor 提交 MR 任务到 YARN
→ 读写 HDFS 文件 → 返回结果

三、配置 Hive 服务

3.1 HiveServer2 远程连接

若需要远程连接 Hive(如通过 DataGrip、JDBC 等),必须开启 HiveServer2 服务。

第一步:配置 Hadoop 的 core-site.xml,设置代理用户权限,使 HiveServer2 可以直接操作 NameNode 和 ResourceManager:

<!-- 配置所有节点的指定用户都可以作为代理用户 -->
<property>
    <name>hadoop.proxyuser.<用户>.hosts</name>
    <value>*</value>
</property>
<property>
    <name>hadoop.proxyuser.<用户>.groups</name>
    <value>*</value>
</property>
<property>
    <name>hadoop.proxyuser.<用户>.users</name>
    <value>*</value>
</property>

配置完成后需要分发到所有集群节点。

第二步:配置 Hive 的 hive-site.xml,指定 HiveServer2 的主机和端口:

<property>
    <name>hive.server2.thrift.bind.host</name>
    <value><ip地址></value>
</property>
<property>
    <name>hive.server2.thrift.port</name>
    <value><port端口号></value>
</property>

第三步:配置 Metastore 服务独立运行:

<property>
    <name>hive.metastore.uris</name>
    <value>thrift://<ip地址>:9083</value>
</property>

3.2 后台启动服务

HiveServer2 和 Metastore 服务启动时会独占窗口,通常使用 nohup 后台运行:

nohup hive --service metastore 1>/opt/module/hive-3.1.3/logs/metastore-log 2>&1 &
nohup hive --service hiveserver2 1>/opt/module/hive-3.1.3/logs/hiveserver2-log 2>&1 &

命令解释:

  • nohup — 关闭终端不会 kill 进程
  • 1>log_path 2>&1 — 重定向 stdout 和 stderr 到日志文件
  • & — 进程在后台运行

3.3 其他实用配置

日志目录配置:修改 hive-log4j2.properties.template 中的日志路径,并重命名为 hive-log4j2.properties

property.hive.log.dir = /opt/module/hive-3.1.3/logs

本地模式:日常测试不想跑集群时,可临时切换为本地模式:

set mapreduce.framework.name=local;

本地模式可能会有内存溢出问题。需修改 hive-env.sh 增加 HeapSize 到 2048MB。


四、Hive 客户端使用技巧

4.1 交互式命令

# 执行单条 SQL 后退出
hive -e "SELECT * FROM emp LIMIT 10;"

# 执行整个 SQL 文件后退出
hive -f /path/to/query.sql

4.2 临时修改配置

# 启动时指定配置
hive --hiveconf mapreduce.framework.name=local

# 进入命令行后修改
hive> set mapreduce.framework.name=local;
hive> set mapreduce.framework.name;   -- 查看当前值

五、HQL 基础语法(重点)

以下所有示例基于本地练习环境。

5.1 数据类型

基本数据类型
CREATE TABLE student (
    id      INT,
    name    STRING,
    id_card BIGINT,
    sal     DOUBLE
);

INSERT INTO student VALUES
    (1001, 'zhangsan', 238791939,    38000.00),
    (1002, 'lisi',     28379123909,  32000.00);
类型说明示例
INT整数1001
BIGINT长整数28379123909
STRING字符串‘zhangsan’
DOUBLE双精度浮点38000.00
集合数据类型

Hive 相对于传统关系型数据库,提供了丰富的集合类型 —— ARRAYMAPSTRUCT

-- 数据样例:周杰伦, xiaoming_xiaomei, 青花瓷:29.99_告白气球:32.00, 南山区_深圳_12298

CREATE TABLE singers (
    name    STRING,
    friends ARRAY<STRING>,              -- ["xiaoming", "xiaomei"]
    songs   MAP<STRING, DOUBLE>,        -- {"青花瓷": 29.99, "告白气球": 32.00}
    address STRUCT<region:STRING, city:STRING, post_code:BIGINT>
)
ROW FORMAT DELIMITED
    FIELDS TERMINATED BY ','
    COLLECTION ITEMS TERMINATED BY '_'
    MAP KEYS TERMINATED BY ':'
    LINES TERMINATED BY '\n';

-- 查询集合字段
SELECT name, friends[0], songs['青花瓷'], address.region FROM singers;
类型说明示例
ARRAY数组(元素数据类型相同)array(1,2,3,4,5)
MAP键值对(key数据类型相同,value数据类型相同)map(‘key1’, ‘value1’, ‘key2’, ‘value2’)
STRUCT结构体,类似Java对象named_struct(‘name’, ‘zhangsan’, ‘age’, 18, ‘sex’, ‘男’)

5.2 DDL —— 数据库与表定义

创建数据库
CREATE DATABASE IF NOT EXISTS db1
    COMMENT '练习使用的库'
    LOCATION '/db1'
    WITH DBPROPERTIES ('author'='zhangsan', 'create_time'='2026/3/23');
建表语法全览
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name (
    col_name data_type [COMMENT col_comment], ...
)
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type, ...)]               -- 分区
[CLUSTERED BY (col_name, ...) INTO N BUCKETS]            -- 分桶
[SORTED BY (col_name [ASC|DESC], ...)]                   -- 桶内排序
[ROW FORMAT row_format]
[STORED AS file_format]                                   -- 存储格式(textfile / orc / parquet)
[LOCATION hdfs_path]
[TBLPROPERTIES (key=val, ...)]
[AS select_statement];                                    -- CTAS 建表
内部表 vs 外部表
特性内部表 (Managed Table)外部表 (External Table)
数据生命周期随表删除而删除删除表时数据保留
适用场景仅由 Hive 管理的数据多工具共享的 HDFS 数据
-- 内部表
CREATE TABLE student (id INT, name STRING)
    ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

-- 外部表
CREATE EXTERNAL TABLE student1 (id INT, name STRING)
    ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
表结构修改
-- 重命名
ALTER TABLE singer1 RENAME TO singer3;

-- 新增列
ALTER TABLE singer1 ADD COLUMNS (salary DOUBLE);

-- 修改列
ALTER TABLE singer1 CHANGE COLUMN salary sal DOUBLE;

-- 替换列(慎用,会覆盖所有列)
ALTER TABLE singer1 REPLACE COLUMNS (name1 STRING, friend ARRAY<STRING>);

-- 清空表
TRUNCATE TABLE singer3;

-- 删除表
DROP TABLE singer2;

5.3 DML —— 数据操作

Load 导入
LOAD DATA [LOCAL] INPATH '/path/to/data.txt'
[OVERWRITE] INTO TABLE table_name;
  • LOCAL:从本地(Hive 服务器)上传
  • OVERWRITE:覆盖写入
Insert 导入
-- 追加((注意:每次INSERT INTO会生成新文件,生产环境建议配合分区使用))
INSERT INTO TABLE student1 SELECT * FROM student;

-- 覆盖
INSERT OVERWRITE TABLE student1 SELECT * FROM student;

-- 将查询结果导出到本地/HDFS
INSERT OVERWRITE LOCAL DIRECTORY '/export/path'
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
SELECT * FROM student;
Export / Import 数据导出导入
-- 导出(含元数据,仅支持 HDFS)
EXPORT TABLE student TO '/data/student';

-- 导入(创建新表并恢复数据)
IMPORT TABLE new_student FROM '/data/student';

5.4 DQL —— 数据查询

以经典的 emp(员工表)和 dept(部门表)为例:

-- 部门表
CREATE TABLE dept (
    deptno INT    COMMENT '部门编号',
    dname  STRING COMMENT '部门名称',
    loc    INT    COMMENT '部门位置'
) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

-- 员工表
CREATE TABLE emp (
    empno  INT    COMMENT '员工编号',
    ename  STRING COMMENT '员工姓名',
    job    STRING COMMENT '员工岗位',
    sal    DOUBLE COMMENT '员工薪资',
    deptno INT    COMMENT '部门编号'
) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
JOIN 连接查询
-- 内连接:两表交集
SELECT e.*, d.dname
FROM emp e
JOIN dept d ON e.deptno = d.deptno;

-- 左外连接:左表全部 + 右表交集
SELECT e.*, d.dname
FROM emp e
LEFT JOIN dept d ON e.deptno = d.deptno;

-- 右外连接:左表交集 + 右表全部
SELECT e.*, d.dname
FROM emp e
RIGHT JOIN dept d ON e.deptno = d.deptno;

-- 全连接:两表全部
SELECT e.*, d.dname
FROM emp e
FULL JOIN dept d ON e.deptno = d.deptno;

-- 多表联查
SELECT e.*, d.dname, l.loc_name
FROM emp e
JOIN dept d ON e.deptno = d.deptno
JOIN location l ON d.loc = l.loc;
分组聚合
-- 每个部门的平均薪资
SELECT deptno, AVG(sal) AS avg_sal
FROM emp
GROUP BY deptno;

-- 每个部门最高薪水的人
SELECT t1.deptno, t1.max_sal, t2.ename
FROM (
    SELECT deptno, MAX(sal) AS max_sal
    FROM emp
    GROUP BY deptno
) t1
JOIN emp t2 ON t1.deptno = t2.deptno AND t1.max_sal = t2.sal;
排序
-- 全局排序(Order By):有且仅有一个 Reduce
SELECT * FROM emp ORDER BY deptno;

-- 区内排序(Sort By):每个 Reduce 内部排序,配合 DISTRIBUTE BY 控制分区
SELECT * FROM emp
DISTRIBUTE BY deptno    -- 按 deptno 哈希分区
SORT BY deptno;

-- CLUSTER BY = DISTRIBUTE BY + SORT BY(同一字段,仅升序)
SELECT * FROM emp CLUSTER BY deptno;
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐