Apache Hive 完整知识总结与使用教程
版本参考:Apache Hive 4.x / 3.1.x(当前主流生产版本) 官方网站:https://hive.apache.org/ 官方文档:https://cwiki.apache.org/confluence/display/Hive/Home
目录
- 4.1 前置条件
- 4.2 二进制包安装(传统方式)
- 4.3 配置 MySQL 作为 Metastore
- 4.4 启动 Hive 服务
- 4.5 Docker 快速启动(推荐入门)
- 5.1 数据库操作
- 5.2 表的创建(内部表 vs 外部表)
- 5.3 分区表
- 5.4 分桶表
- 5.5 表结构修改
- 5.6 视图(View)
- 6.1 数据加载(LOAD DATA)
- 6.2 INSERT 语句
- 6.3 SELECT 查询详解
- 6.4 JOIN 操作
- 6.5 子查询与 CTE
- 6.6 窗口函数
- 6.7 ACID 事务(UPDATE / DELETE)
1. Hive 概述
1.1 什么是 Apache Hive?
Apache Hive 是一个构建在 Apache Hadoop 之上的分布式数据仓库软件系统,由 Facebook 于 2007 年开发,后捐献给 Apache 软件基金会。
Hive 的核心价值在于:它提供了类 SQL 的查询语言 HiveQL(HQL),使得熟悉 SQL 的开发者和分析师无需学习 MapReduce 编程即可处理和分析存储在 HDFS 中的海量数据。HiveQL 在底层被自动翻译为 MapReduce、Apache Tez 或 Apache Spark 作业执行。
开发者写 HQL 查询 → Hive 编译优化 → 生成 MapReduce/Tez/Spark 作业 → 在 YARN 上执行 → 结果写回 HDFS
1.2 Hive 解决了什么问题?
| 必须用 Java 编写 MapReduce 程序 | HQL(类 SQL),门槛极低 |
| 开发周期长,调试困难 | 声明式查询,框架自动生成执行计划 |
| 无法方便地管理结构化数据的 Schema | Metastore 统一管理表结构、分区等元数据 |
| 缺乏数据发现和数据抽象机制 | 提供数据仓库级别的抽象:数据库、表、分区、视图 |
| 批量数据分析没有统一入口 | 标准 JDBC/ODBC 接口,BI 工具可直接对接 |
1.3 Hive 的核心特性
- SQL 接口:支持 SQL:2003、SQL:2011、SQL:2016 大量标准功能,降低大数据学习门槛
- 可扩展性:通过 UDF/UDAF/UDTF 支持自定义函数,通过 SerDe 扩展支持的数据格式
- 多执行引擎:支持 MapReduce、Apache Tez、Apache Spark 作为底层执行引擎
- 多存储格式:支持 TextFile、ORC、Parquet、Avro、RCFile 等多种文件格式
- 元数据管理:HMS(Hive Metastore Service)提供集中式元数据存储和管理
- 分区与分桶:通过分区(Partition)和分桶(Bucketing)优化查询性能
- ACID 支持:Hive 0.14+ 支持行级 INSERT/UPDATE/DELETE(需 ORC 格式 + 事务配置)
- Sub-second 查询:通过 LLAP(Live Long and Process)实现交互式亚秒级查询
- 多云兼容:支持 HDFS、Amazon S3、Azure ADLS、Google Cloud Storage 等存储后端
1.4 Hive 发展历程
| Hive 0.x(初始版本) | 2008~2012 | Facebook 开源,基本 DDL/DML,仅支持 MapReduce |
| Hive 0.13 | 2014 | 原生支持 Parquet 格式 |
| Hive 0.14 | 2014 | ACID 事务支持(UPDATE/DELETE),ORC 格式 |
| Hive 2.0 | 2016 | LLAP(交互式查询),HiveServer2 改进,Hive CLI 弃用 |
| Hive 3.0 | 2018 | 移除索引,ACID 默认开启,Druid 集成,去除旧 API |
| Hive 3.1.x | 2019~2022 | 主流生产版本,稳定性大幅提升 |
| Hive 4.0 | 2024 | JDK 21 支持、Iceberg v3 深度集成、REST Catalog、删除向量 |
| Hive 4.2.0 | 2025 | 当前最新版,增强 Iceberg 功能、自动 compaction |
1.5 Hive 适用场景 vs 不适用场景
✅ 适用场景:
- 大规模离线数据仓库(ETL、报表、数据分析)
- PB 级数据的批量处理
- 数据湖架构中的结构化查询层
- BI 工具(Tableau、Power BI 等)通过 JDBC 对接大数据平台
- 数据迁移和数据质量检查
❌ 不适用场景:
- 在线事务处理(OLTP):延迟高(秒到分钟级),不适合实时交易
- 低延迟查询(<100ms 响应):应使用 HBase、Druid、ClickHouse
- 频繁的小数据量增删改:ACID 支持有限,效率低
- 实时流数据处理:应使用 Apache Flink 或 Spark Streaming
2. Hive 核心架构
2.1 整体架构图
┌──────────────────────────────────────────────────────────────────┐
│ Client 层 │
│ CLI(hive shell) | Beeline(JDBC/ODBC)| Web UI | JDBC/ODBC │
└───────────────────────────────┬──────────────────────────────────┘
│ HQL 查询
▼
┌──────────────────────────────────────────────────────────────────┐
│ HiveServer2 服务层 │
│ Thrift Server(处理远程连接,支持多并发认证) │
└───────────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Driver │ │ Metastore│ │ Compiler │
│(会话管理)│◄─────────►│(元数据) │◄─────────►│(查询解析)│
└──────────┘ └──────────┘ └──────────┘
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ RDBMS(MySQL等) │ │
│ │ (持久化元数据) │ │
│ └──────────────────┘ │
│ │
▼ ┌────────────────────► │
┌──────────┐ │ ▼
│Optimizer │◄────────────────┘ ┌──────────────┐
│(查询优化)│ │ Execution │
└──────────┘ │ Engine │
│ MapReduce / │
│ Tez /Spark │
└──────┬───────┘
│
┌───────────────────────┤
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│ YARN │ │ HDFS │
│(资源调度)│ │(数据存储)│
└──────────┘ └──────────┘
2.2 核心组件详解
① UI(用户界面)
用户提交 HQL 查询和操作的入口,包括:
- Hive CLI:命令行工具,已在 Hive 2.0 后被弃用,生产不推荐使用
- Beeline:基于 JDBC 的客户端 CLI,通过 HiveServer2 连接,推荐使用
- HWI(Web Interface):Web 界面,已废弃
- JDBC/ODBC:通过 HiveServer2 对接 BI 工具和应用程序
② Driver(驱动)
负责管理 HQL 语句的完整生命周期:
- 接收来自 UI 的 HQL 语句
- 创建和管理 Session Handle(会话句柄)
- 提供 JDBC/ODBC 兼容接口
- 协调 Compiler、Optimizer、Executor 的工作
- 管理执行进度和结果获取
③ Compiler(编译器)
HQL 语句的解析与编译核心:
HQL 文本 → Token → AST → Operator Tree → DAG of Stages → 物理执行计划
④ Optimizer(优化器)
对编译器生成的执行计划进行变换优化:
- 谓词下推(Predicate Pushdown):将过滤条件尽早执行,减少数据量
- 列裁剪(Column Pruning):只读取查询中用到的列
- 分区裁剪(Partition Pruning):根据分区条件跳过无关分区
- Join 重排序(Join Reordering):将小表放在 Join 的驱动侧
- 公共子表达式消除:避免重复计算
- 使用 CBO(Cost-Based Optimizer):基于统计信息(ANALYZE TABLE)选择最优计划
⑤ Metastore(元数据存储)
Hive 最重要的基础设施之一,存储所有表和分区的元数据:
| 数据库信息 | 数据库名、描述、HDFS 路径 |
| 表信息 | 表名、列名、数据类型、注释、HDFS 位置、存储格式 |
| 分区信息 | 分区键、分区值、对应 HDFS 路径 |
| SerDe 信息 | 序列化/反序列化类及属性 |
| 统计信息 | 行数、列的 distinct 值数、最大/最小值等(ANALYZE TABLE 生成) |
Metastore 将元数据存储在关系型数据库(默认 Derby,生产用 MySQL/PostgreSQL)中,通过 Thrift 服务对外暴露。
⑥ Execution Engine(执行引擎)
将优化后的执行计划提交给底层计算框架执行:
- 与 YARN ResourceManager 交互,申请计算资源
- 监控 Job 执行进度
- 处理 Task 失败重试
- 支持 MapReduce、Tez、Spark 三种引擎(可在会话级别切换)
3. Hive 数据模型
Hive 的数据模型层次从大到小为:Database → Table → Partition → Bucket
3.1 Database(数据库)
类似于关系型数据库中的 Schema,是表的命名空间。
— 创建数据库(在 HDFS 中对应一个目录 /user/hive/warehouse/<db_name>.db/)
CREATE DATABASE IF NOT EXISTS sales_db
COMMENT 'Sales data warehouse'
LOCATION '/data/hive/sales'
WITH DBPROPERTIES ('creator'='admin', 'date'='2024-01-01');
3.2 Table(表)
Hive 中有两种核心表类型:
内部表(Managed Table)
默认表类型,Hive 完全管理数据的生命周期。
DROP TABLE 时,HDFS 上的数据文件也会被删除。
数据存储在 hive.metastore.warehouse.dir 配置的目录下(默认 /user/hive/warehouse/<db>/<table>/)。
外部表(External Table)
Hive 只管理元数据,不管理实际数据。
DROP TABLE 时,只删除元数据,HDFS 上的数据文件不受影响。
适合数据在 HDFS/S3 上已经存在、由其他工具管理的场景。
3.3 Partition(分区)
将表数据按某一列(分区键)的值划分到不同的 HDFS 子目录中,查询时通过分区裁剪跳过不相关数据:
/user/hive/warehouse/orders/
dt=2024-01-01/ ← 分区目录
dt=2024-01-02/
dt=2024-01-03/
分区列不存储在数据文件中,而是体现在目录结构里。
3.4 Bucket(桶/分桶)
在分区(或表)的基础上,进一步将数据按某列的哈希值分散到固定数量的文件(桶)中:
/user/hive/warehouse/orders/dt=2024-01-01/
000000_0 ← 桶 0
000001_0 ← 桶 1
000002_0 ← 桶 2
000003_0 ← 桶 3
分桶的好处:
- 高效 Bucket JOIN:两张表按相同列以相同桶数分桶,Join 时无需全表扫描
- 高效 TABLESAMPLE:按桶抽样,效率远高于 RAND() 抽样
- 数据均匀分布:避免数据倾斜
4. 安装与环境配置
4.1 前置条件
| 操作系统 | Linux(Ubuntu 20.04+ / CentOS 7+) |
| Java | JDK 8(Hive 3.x)或 JDK 11/17/21(Hive 4.x) |
| Hadoop | 已安装运行的 Hadoop 集群(HDFS + YARN) |
| 数据库 | Derby(测试)/ MySQL 5.7+(生产)/ PostgreSQL 12+(生产) |
| 内存 | 推荐 ≥ 8GB RAM |
4.2 二进制包安装(传统方式)
步骤一:下载并解压 Hive
# 从 https://hive.apache.org/downloads.html 获取最新版本
# 以 Hive 3.1.3 为例
wget https://downloads.apache.org/hive/hive-3.1.3/apache-hive-3.1.3-bin.tar.gz
tar -xzf apache-hive-3.1.3-bin.tar.gz
sudo mv apache-hive-3.1.3-bin /usr/local/hive
步骤二:配置环境变量
编辑 ~/.bashrc 或 /etc/profile,追加:
export HIVE_HOME=/usr/local/hive
export PATH=$PATH:$HIVE_HOME/bin
export HIVE_CONF_DIR=$HIVE_HOME/conf
source ~/.bashrc
hive –version # 验证安装
步骤三:创建 HDFS 仓库目录
hdfs dfs -mkdir -p /user/hive/warehouse
hdfs dfs -mkdir -p /tmp/hive
hdfs dfs -chmod 777 /user/hive/warehouse
hdfs dfs -chmod 777 /tmp/hive
步骤四:配置 hive-site.xml
cp $HIVE_HOME/conf/hive-default.xml.template $HIVE_HOME/conf/hive-site.xml
vim $HIVE_HOME/conf/hive-site.xml
最小化配置(使用嵌入式 Derby,仅用于测试):
<configuration>
<!– Hive 数据仓库在 HDFS 中的位置 –>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
<!– Hive 临时文件目录 –>
<property>
<name>hive.exec.scratchdir</name>
<value>/tmp/hive</value>
</property>
<!– 执行引擎(mr | tez | spark) –>
<property>
<name>hive.execution.engine</name>
<value>tez</value>
</property>
<!– 启用动态分区 –>
<property>
<name>hive.exec.dynamic.partition</name>
<value>true</value>
</property>
<property>
<name>hive.exec.dynamic.partition.mode</name>
<value>nonstrict</value>
</property>
</configuration>
步骤五:初始化 Schema(使用 Derby)
# 初始化 Derby 元数据 Schema(只需执行一次)
schematool -dbType derby -initSchema
# 验证
hive
hive> SHOW DATABASES;
4.3 配置 MySQL 作为 Metastore(生产推荐)
步骤一:安装 MySQL 并创建元数据库
sudo apt install -y mysql-server
sudo mysql_secure_installation
# 登录 MySQL 创建用户和数据库
mysql -u root -p
— 在 MySQL 中执行
CREATE DATABASE metastore DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
CREATE USER 'hive'@'%' IDENTIFIED BY 'hive_password';
GRANT ALL PRIVILEGES ON metastore.* TO 'hive'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;
步骤二:添加 MySQL JDBC 驱动
# 下载 MySQL Connector/J
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.33.tar.gz
tar -xzf mysql-connector-java-8.0.33.tar.gz
cp mysql-connector-java-8.0.33/mysql-connector-java-8.0.33.jar $HIVE_HOME/lib/
步骤三:修改 hive-site.xml 指向 MySQL
<configuration>
<!– Hive 仓库目录 –>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
<!– MySQL 连接信息 –>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://localhost:3306/metastore?createDatabaseIfNotExist=true&useSSL=false&serverTimezone=UTC</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>hive</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>hive_password</value>
</property>
<!– Metastore 服务地址(远程模式) –>
<property>
<name>hive.metastore.uris</name>
<value>thrift://localhost:9083</value>
</property>
<!– HiveServer2 配置 –>
<property>
<name>hive.server2.thrift.port</name>
<value>10000</value>
</property>
<property>
<name>hive.server2.thrift.bind.host</name>
<value>0.0.0.0</value>
</property>
<!– 关闭 doAs(单用户测试时) –>
<property>
<name>hive.server2.enable.doAs</name>
<value>false</value>
</property>
<!– 动态分区配置 –>
<property>
<name>hive.exec.dynamic.partition</name>
<value>true</value>
</property>
<property>
<name>hive.exec.dynamic.partition.mode</name>
<value>nonstrict</value>
</property>
</configuration>
步骤四:初始化 MySQL Metastore Schema
schematool -dbType mysql -initSchema
# 验证 schema 版本
schematool -dbType mysql -info
4.4 启动 Hive 服务
# 1. 确保 Hadoop 已启动
jps | grep -E "NameNode|DataNode|ResourceManager|NodeManager"
# 2. 启动 Metastore 服务(后台运行)
hive –service metastore &
# 或
nohup hive –service metastore > /tmp/metastore.log 2>&1 &
# 验证 Metastore 是否在 9083 端口监听
netstat -tuln | grep 9083
# 3. 启动 HiveServer2(后台运行)
hive –service hiveserver2 &
# 或
nohup hive –service hiveserver2 > /tmp/hiveserver2.log 2>&1 &
# 验证 HiveServer2 是否在 10000 端口监听
netstat -tuln | grep 10000
# 4. 访问 HiveServer2 Web UI
# http://localhost:10002
4.5 Docker 快速启动(入门推荐)
这是最快速的入门方式,官方提供完整 Docker 镜像:
export HIVE_VERSION=4.0.1
# 方式一:最简单,使用嵌入式 Derby,数据不持久化(快速体验)
docker run -d -p 10000:10000 -p 10002:10002 \\
–env SERVICE_NAME=hiveserver2 \\
–name hive4 \\
apache/hive:${HIVE_VERSION}
# 连接到 Beeline
docker exec -it hive4 beeline -u 'jdbc:hive2://localhost:10000/'
# 方式二:使用 docker-compose,HiveServer2 + Metastore + PostgreSQL(数据持久化)
# 创建 compose.yaml 文件
cat > compose.yaml << 'EOF'
version: "3"
services:
postgres:
image: postgres:17.2
environment:
POSTGRES_PASSWORD: "hivepassword"
POSTGRES_DB: "metastore"
volumes:
– postgres-data:/var/lib/postgresql/data
metastore:
image: apache/hive:4.0.1
depends_on:
– postgres
environment:
SERVICE_NAME: metastore
DB_DRIVER: postgres
SERVICE_OPTS: >-
-Djavax.jdo.option.ConnectionDriverName=org.postgresql.Driver
-Djavax.jdo.option.ConnectionURL=jdbc:postgresql://postgres:5432/metastore
-Djavax.jdo.option.ConnectionUserName=postgres
-Djavax.jdo.option.ConnectionPassword=hivepassword
ports:
– "9083:9083"
hiveserver2:
image: apache/hive:4.0.1
depends_on:
– metastore
environment:
SERVICE_NAME: hiveserver2
IS_RESUME: "true"
SERVICE_OPTS: "-Dhive.metastore.uris=thrift://metastore:9083"
ports:
– "10000:10000"
– "10002:10002"
volumes:
– warehouse:/opt/hive/data/warehouse
volumes:
postgres-data:
warehouse:
EOF
docker-compose up -d
# 连接 Beeline
docker exec -it hiveserver2-container beeline -u 'jdbc:hive2://localhost:10000/'
5. HiveQL DDL 数据定义语言
5.1 数据库操作
— 创建数据库
CREATE DATABASE IF NOT EXISTS mydb
COMMENT '我的数据仓库'
LOCATION '/data/hive/mydb'
WITH DBPROPERTIES ('owner'='dataeng', 'version'='1.0');
— 查看数据库列表
SHOW DATABASES;
SHOW DATABASES LIKE 'my*'; — 支持通配符
— 查看数据库详情
DESCRIBE DATABASE EXTENDED mydb;
— 切换数据库
USE mydb;
— 删除数据库(CASCADE 同时删除表)
DROP DATABASE IF EXISTS mydb CASCADE;
— 修改数据库属性
ALTER DATABASE mydb SET DBPROPERTIES ('updated_by'='admin');
5.2 表的创建(内部表 vs 外部表)
完整的 CREATE TABLE 语法
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
(
col_name data_type [COMMENT 'column comment'],
...
)
[COMMENT 'table comment']
[PARTITIONED BY (col_name data_type [COMMENT ...], ...)]
[CLUSTERED BY (col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
[ROW FORMAT row_format]
[STORED AS file_format]
[LOCATION 'hdfs_path']
[TBLPROPERTIES (property_name=property_value, ...)]
[AS select_statement]
内部表示例
— 基本内部表
CREATE TABLE IF NOT EXISTS employees (
emp_id INT COMMENT '员工ID',
name STRING COMMENT '姓名',
dept STRING COMMENT '部门',
salary DOUBLE COMMENT '薪资',
hire_date DATE COMMENT '入职日期',
skills ARRAY<STRING> COMMENT '技能列表',
address STRUCT<city:STRING, zip:STRING> COMMENT '地址'
)
COMMENT '员工信息表'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\\t'
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':'
LINES TERMINATED BY '\\n'
STORED AS TEXTFILE
TBLPROPERTIES ('author'='admin', 'create_time'='2024-01-01');
— 使用 ORC 格式(推荐生产使用)
CREATE TABLE orders_orc (
order_id BIGINT,
user_id INT,
amount DECIMAL(10,2),
create_time TIMESTAMP
)
STORED AS ORC
TBLPROPERTIES ('orc.compress'='SNAPPY');
— 使用 CTAS(Create Table As Select)从已有表创建
CREATE TABLE dept_summary
STORED AS ORC
AS
SELECT dept, COUNT(*) AS cnt, AVG(salary) AS avg_salary
FROM employees
GROUP BY dept;
外部表示例
— 创建外部表,指向 HDFS 上已有数据
CREATE EXTERNAL TABLE web_logs (
ip STRING,
log_time STRING,
request STRING,
status INT,
bytes BIGINT
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ' '
STORED AS TEXTFILE
LOCATION '/data/weblogs/2024/'
TBLPROPERTIES ('skip.header.line.count'='1'); — 跳过 CSV 头行
— 外部表(Parquet 格式,指向 S3)
CREATE EXTERNAL TABLE s3_events (
event_id STRING,
event_type STRING,
user_id BIGINT,
event_time TIMESTAMP
)
STORED AS PARQUET
LOCATION 's3a://my-bucket/events/';
查看表信息
SHOW TABLES; — 列出所有表
SHOW TABLES LIKE 'order*'; — 模糊查找
DESCRIBE employees; — 查看表结构(列名、类型)
DESCRIBE FORMATTED employees; — 查看详细信息(包括 HDFS 路径、格式等)
DESCRIBE EXTENDED employees; — 查看更详细信息(包括原始元数据)
SHOW CREATE TABLE employees; — 查看建表语句
SHOW TBLPROPERTIES employees; — 查看表属性
5.3 分区表
— 创建分区表(按日期分区)
CREATE TABLE user_events (
user_id BIGINT,
event_type STRING,
event_time TIMESTAMP,
page_url STRING
)
PARTITIONED BY (
dt STRING COMMENT '日期分区,格式 yyyy-MM-dd',
country STRING COMMENT '国家分区'
)
STORED AS ORC;
— 手动添加分区(静态分区)
ALTER TABLE user_events ADD PARTITION (dt='2024-01-01', country='CN')
LOCATION '/data/events/dt=2024-01-01/country=CN';
— 添加多个分区
ALTER TABLE user_events ADD
PARTITION (dt='2024-01-02', country='CN')
PARTITION (dt='2024-01-02', country='US');
— 删除分区(同时删除数据,如果是内部表)
ALTER TABLE user_events DROP PARTITION (dt='2023-12-01');
ALTER TABLE user_events DROP PARTITION (dt < '2023-01-01'); — 按条件批量删除
— 查看分区列表
SHOW PARTITIONS user_events;
SHOW PARTITIONS user_events PARTITION (dt='2024-01-01');
— 修复分区(当 HDFS 目录已存在但 Metastore 没有记录时)
MSCK REPAIR TABLE user_events;
— 查询时分区裁剪(必须加分区条件,否则全表扫描)
SELECT COUNT(*) FROM user_events WHERE dt='2024-01-01' AND country='CN';
5.4 分桶表
— 创建分桶表(按 user_id 哈希分为 32 个桶)
CREATE TABLE user_orders (
order_id BIGINT,
user_id INT,
amount DOUBLE,
status STRING
)
CLUSTERED BY (user_id) SORTED BY (order_id ASC) INTO 32 BUCKETS
STORED AS ORC;
— 同时使用分区和分桶
CREATE TABLE user_behavior (
user_id BIGINT,
action STRING,
item_id BIGINT
)
PARTITIONED BY (dt STRING)
CLUSTERED BY (user_id) INTO 256 BUCKETS
STORED AS ORC;
— 向分桶表插入数据(必须启用 bucketing 支持)
SET hive.enforce.bucketing = true; — Hive 1.x 需要,2.x+ 已默认
INSERT INTO user_orders SELECT order_id, user_id, amount, status FROM raw_orders;
— 分桶采样查询
SELECT * FROM user_orders TABLESAMPLE(BUCKET 1 OUT OF 32 ON user_id); — 取第1个桶
SELECT * FROM user_orders TABLESAMPLE(BUCKET 1 OUT OF 8 ON user_id); — 取前4个桶(32/8=4)
5.5 表结构修改
— 重命名表
ALTER TABLE employees RENAME TO staff;
— 添加列
ALTER TABLE employees ADD COLUMNS (
phone STRING COMMENT '手机号',
email STRING COMMENT '邮箱'
);
— 修改列(改名/改类型)
ALTER TABLE employees CHANGE COLUMN name full_name STRING COMMENT '全名';
— 替换所有列(重新定义列结构)
ALTER TABLE employees REPLACE COLUMNS (
emp_id INT,
full_name STRING,
salary DOUBLE
);
— 修改表属性
ALTER TABLE employees SET TBLPROPERTIES ('last_modified_by'='admin');
— 修改存储格式
ALTER TABLE employees SET FILEFORMAT ORC;
— 修改表位置
ALTER TABLE employees SET LOCATION '/new/hdfs/path/';
— 分区表修改分区属性
ALTER TABLE user_events PARTITION (dt='2024-01-01') SET FILEFORMAT ORC;
— 合并小文件(ORC 格式支持)
ALTER TABLE user_events PARTITION (dt='2024-01-01') CONCATENATE;
5.6 视图(View)
— 创建视图
CREATE VIEW IF NOT EXISTS active_employees AS
SELECT emp_id, name, dept, salary
FROM employees
WHERE hire_date > '2020-01-01' AND salary > 5000;
— 查询视图(和查询普通表一样)
SELECT dept, COUNT(*) FROM active_employees GROUP BY dept;
— 修改视图
ALTER VIEW active_employees AS
SELECT emp_id, name, dept, salary, hire_date
FROM employees
WHERE salary > 8000;
— 删除视图
DROP VIEW IF EXISTS active_employees;
— 物化视图(Hive 3.0+,需要 ACID)
CREATE MATERIALIZED VIEW emp_dept_summary
AS SELECT dept, COUNT(*) cnt, AVG(salary) avg_sal
FROM employees GROUP BY dept;
— 重建物化视图(更新缓存)
ALTER MATERIALIZED VIEW emp_dept_summary REBUILD;
6. HiveQL DML 数据操作语言
6.1 数据加载(LOAD DATA)
— 从本地文件系统加载(LOCAL 关键字表示本地文件)
— 注意:会将文件移动/复制到 HDFS 仓库目录
LOAD DATA LOCAL INPATH '/home/user/data/employees.csv'
INTO TABLE employees;
— 加载并覆盖现有数据
LOAD DATA LOCAL INPATH '/home/user/data/employees.csv'
OVERWRITE INTO TABLE employees;
— 从 HDFS 加载(不加 LOCAL,文件从 HDFS 移动到表目录)
LOAD DATA INPATH '/data/raw/employees.csv'
INTO TABLE employees;
— 加载数据到特定分区
LOAD DATA LOCAL INPATH '/data/events_20240101.csv'
INTO TABLE user_events PARTITION (dt='2024-01-01', country='CN');
注意:LOAD DATA 是纯文件移动操作,不进行 MapReduce,速度很快。它不会验证数据格式和类型。
6.2 INSERT 语句
— INSERT INTO(追加数据)
INSERT INTO TABLE employees VALUES
(1001, 'Alice', 'Engineering', 12000.00, '2022-03-15'),
(1002, 'Bob', 'Marketing', 9500.00, '2021-07-01');
— INSERT OVERWRITE(覆盖数据)
INSERT OVERWRITE TABLE dept_summary
SELECT dept, COUNT(*) cnt, AVG(salary) avg_sal
FROM employees GROUP BY dept;
— 动态分区插入(自动根据查询结果创建分区)
SET hive.exec.dynamic.partition.mode = nonstrict;
INSERT OVERWRITE TABLE user_events PARTITION (dt, country)
SELECT user_id, event_type, event_time, page_url, dt, country
FROM raw_events
WHERE dt >= '2024-01-01';
— 多目标插入(一次扫描,写多张表,性能优化技巧)
FROM employees
INSERT OVERWRITE TABLE high_salary_emp
SELECT * WHERE salary > 15000
INSERT INTO TABLE mid_salary_emp
SELECT * WHERE salary BETWEEN 8000 AND 15000
INSERT INTO TABLE low_salary_emp
SELECT * WHERE salary < 8000;
— INSERT INTO … SELECT(从查询结果插入)
INSERT INTO TABLE orders_backup
SELECT * FROM orders WHERE YEAR(create_time) = 2023;
6.3 SELECT 查询详解
— 基本查询
SELECT emp_id, name, salary
FROM employees
WHERE dept = 'Engineering' AND salary > 10000
ORDER BY salary DESC
LIMIT 10;
— 聚合查询
SELECT dept,
COUNT(*) AS employee_count,
AVG(salary) AS avg_salary,
MAX(salary) AS max_salary,
MIN(salary) AS min_salary,
SUM(salary) AS total_salary
FROM employees
GROUP BY dept
HAVING COUNT(*) > 5
ORDER BY avg_salary DESC;
— DISTINCT
SELECT DISTINCT dept FROM employees;
SELECT COUNT(DISTINCT dept) FROM employees; — 统计唯一部门数
— 正则表达式查询(REGEXP / RLIKE)
SELECT name FROM employees WHERE name RLIKE '^A.*';
SELECT name FROM employees WHERE name REGEXP 'Alice|Bob';
— LIKE 模糊查询
SELECT name FROM employees WHERE name LIKE 'A%';
SELECT name FROM employees WHERE name LIKE '_ob'; — 下划线匹配单个字符
— BETWEEN … AND
SELECT * FROM employees WHERE salary BETWEEN 8000 AND 12000;
— IN 子句
SELECT * FROM employees WHERE dept IN ('Engineering', 'Marketing', 'Finance');
— IS NULL / IS NOT NULL
SELECT * FROM employees WHERE email IS NULL;
— CASE WHEN
SELECT name,
salary,
CASE
WHEN salary >= 15000 THEN '高薪'
WHEN salary >= 10000 THEN '中薪'
ELSE '低薪'
END AS salary_level
FROM employees;
— SORT BY vs ORDER BY vs DISTRIBUTE BY vs CLUSTER BY
— ORDER BY: 全局排序(只有一个 Reducer),大数据量慎用
SELECT * FROM employees ORDER BY salary DESC;
— SORT BY: 每个 Reducer 内部排序(局部有序)
SELECT * FROM employees SORT BY salary DESC;
— DISTRIBUTE BY: 按指定列分发到 Reducer(常与 SORT BY 配合)
SELECT * FROM employees DISTRIBUTE BY dept SORT BY dept, salary DESC;
— CLUSTER BY: 等价于 DISTRIBUTE BY col SORT BY col(相同列升序)
SELECT * FROM employees CLUSTER BY dept;
— LIMIT 与 OFFSET
SELECT * FROM employees ORDER BY salary DESC LIMIT 10;
SELECT * FROM employees ORDER BY salary DESC LIMIT 10 OFFSET 20; — 第 21-30 条
— TABLESAMPLE 数据采样
SELECT * FROM employees TABLESAMPLE(10 PERCENT); — 随机采样 10%
SELECT * FROM employees TABLESAMPLE(1000 ROWS); — 采样 1000 行
SELECT * FROM user_orders TABLESAMPLE(BUCKET 2 OUT OF 32 ON user_id); — 桶采样
— LATERAL VIEW EXPLODE(展开数组/Map 列)
SELECT emp_id, name, skill
FROM employees
LATERAL VIEW EXPLODE(skills) tmp AS skill;
— LATERAL VIEW json_tuple(解析 JSON)
SELECT base.id, jt.name, jt.age
FROM json_table base
LATERAL VIEW json_tuple(base.json_col, 'name', 'age') jt AS name, age;
6.4 JOIN 操作
— INNER JOIN
SELECT e.name, e.salary, d.dept_name, d.location
FROM employees e
INNER JOIN departments d ON e.dept = d.dept_id;
— LEFT OUTER JOIN
SELECT e.name, d.dept_name
FROM employees e
LEFT JOIN departments d ON e.dept = d.dept_id;
— RIGHT OUTER JOIN
SELECT e.name, d.dept_name
FROM employees e
RIGHT JOIN departments d ON e.dept = d.dept_id;
— FULL OUTER JOIN
SELECT e.name, d.dept_name
FROM employees e
FULL OUTER JOIN departments d ON e.dept = d.dept_id;
— CROSS JOIN(笛卡尔积,谨慎使用!)
SELECT e.name, d.dept_name
FROM employees e CROSS JOIN departments d;
— LEFT SEMI JOIN(相当于 EXISTS,效率高于子查询)
SELECT e.*
FROM employees e
LEFT SEMI JOIN high_salary_list h ON e.emp_id = h.emp_id;
— MAP JOIN(小表 JOIN,广播到所有 Map 端,避免 Reduce)
— 自动触发条件:hive.auto.convert.join=true 且小表 < hive.mapjoin.smalltable.filesize
SELECT /*+ MAPJOIN(d) */
e.name, d.dept_name
FROM employees e
JOIN departments d ON e.dept = d.dept_id;
— Bucket Map Join(两张表均按相同列分桶时效率最高)
— 需要设置:set hive.optimize.bucketmapjoin=true
6.5 子查询与 CTE
— 子查询(IN)
SELECT * FROM employees
WHERE dept IN (
SELECT dept_id FROM departments WHERE location = 'Beijing'
);
— 子查询(EXISTS)
SELECT * FROM employees e
WHERE EXISTS (
SELECT 1 FROM high_performers h WHERE h.emp_id = e.emp_id
);
— FROM 子句中的子查询
SELECT dept, avg_sal
FROM (
SELECT dept, AVG(salary) AS avg_sal
FROM employees
GROUP BY dept
) t
WHERE avg_sal > 10000;
— CTE(Common Table Expression,WITH 子句)—— Hive 0.13+
WITH
dept_stats AS (
SELECT dept, COUNT(*) cnt, AVG(salary) avg_sal
FROM employees
GROUP BY dept
),
high_dept AS (
SELECT dept FROM dept_stats WHERE avg_sal > 10000
)
SELECT e.name, e.salary, e.dept
FROM employees e
JOIN high_dept h ON e.dept = h.dept;
6.6 窗口函数(Window Functions)
窗口函数是 Hive 中非常强大的分析工具:
— 语法:function() OVER ([PARTITION BY …] [ORDER BY …] [frame_clause])
— ROW_NUMBER:每行一个唯一序号
SELECT name, dept, salary,
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn
FROM employees;
— RANK:允许并列,跳号(1,1,3)
SELECT name, dept, salary,
RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS rnk
FROM employees;
— DENSE_RANK:允许并列,不跳号(1,1,2)
SELECT name, dept, salary,
DENSE_RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS dense_rnk
FROM employees;
— 取每个部门工资前3名(ROW_NUMBER 去重)
SELECT * FROM (
SELECT name, dept, salary,
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn
FROM employees
) t WHERE rn <= 3;
— LAG / LEAD:访问前/后 N 行数据
SELECT name, salary,
LAG(salary, 1, 0) OVER (PARTITION BY dept ORDER BY hire_date) AS prev_salary,
LEAD(salary, 1, 0) OVER (PARTITION BY dept ORDER BY hire_date) AS next_salary
FROM employees;
— FIRST_VALUE / LAST_VALUE
SELECT name, dept, salary,
FIRST_VALUE(name) OVER (PARTITION BY dept ORDER BY salary DESC) AS top_earner
FROM employees;
— SUM/AVG/COUNT 累计汇总
SELECT name, dept, salary,
SUM(salary) OVER (PARTITION BY dept ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total,
AVG(salary) OVER (PARTITION BY dept) AS dept_avg,
COUNT(*) OVER () AS total_employees
FROM employees;
— NTILE:将数据分成 N 等份
SELECT name, salary,
NTILE(4) OVER (ORDER BY salary) AS quartile
FROM employees;
— PERCENT_RANK / CUME_DIST
SELECT name, salary,
PERCENT_RANK() OVER (ORDER BY salary) AS pct_rank,
CUME_DIST() OVER (ORDER BY salary) AS cume_dist
FROM employees;
— 帧规范(Frame Specification)
— ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW → 从头到当前行
— ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING → 前2行到后2行(滑动窗口)
— RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING → 当前行到末尾
SELECT name, salary,
AVG(salary) OVER (
PARTITION BY dept
ORDER BY hire_date
ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING
) AS moving_avg
FROM employees;
6.7 ACID 事务(UPDATE / DELETE)
Hive 0.14+ 支持行级别的 UPDATE/DELETE,但需要满足以下条件:
— 前置配置(hive-site.xml 或 SET 命令)
SET hive.support.concurrency = true;
SET hive.enforce.bucketing = true;
SET hive.exec.dynamic.partition.mode = nonstrict;
SET hive.txn.manager = org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
SET hive.compactor.initiator.on = true;
SET hive.compactor.worker.threads = 1;
— 建表必须使用 ORC 格式 + TRANSACTIONAL 属性
CREATE TABLE student (
id INT,
name STRING,
score INT
)
CLUSTERED BY (id) INTO 4 BUCKETS
STORED AS ORC
TBLPROPERTIES ('transactional'='true');
— UPDATE 语句
UPDATE student SET score = 95 WHERE id = 1001;
UPDATE student SET name = 'Alice Zhang', score = score + 5 WHERE name = 'Alice';
— DELETE 语句
DELETE FROM student WHERE id = 1005;
DELETE FROM student WHERE score < 60;
— MERGE(Hive 2.2+,Upsert 操作)
MERGE INTO student AS target
USING updates AS source
ON target.id = source.id
WHEN MATCHED AND source.action = 'UPDATE' THEN
UPDATE SET name = source.name, score = source.score
WHEN MATCHED AND source.action = 'DELETE' THEN DELETE
WHEN NOT MATCHED THEN
INSERT VALUES (source.id, source.name, source.score);
7. Hive 数据类型详解
7.1 基本数据类型
| TINYINT | 1B | -128 ~ 127 | 100Y |
| SMALLINT | 2B | -32768 ~ 32767 | 1000S |
| INT / INTEGER | 4B | -2^31 ~ 2^31-1 | 100 |
| BIGINT | 8B | -2^63 ~ 2^63-1 | 100L |
| FLOAT | 4B | 单精度浮点数 | 3.14 |
| DOUBLE | 8B | 双精度浮点数 | 3.14159265 |
| DECIMAL(p,s) | 可变 | 精确小数,p 总精度,s 小数位 | DECIMAL(10,2) |
| BOOLEAN | – | TRUE / FALSE | true |
| STRING | 可变 | 无长度限制的字符串(UTF-8) | 'hello' |
| VARCHAR(n) | 可变 | 最大长度 n 的字符串 | VARCHAR(255) |
| CHAR(n) | 固定 | 固定长度字符串,不足补空格 | CHAR(10) |
| BINARY | 可变 | 字节数组 | – |
| TIMESTAMP | – | 纳秒精度时间戳 | '2024-01-01 12:00:00' |
| DATE | – | 仅日期(无时间) | '2024-01-01' |
| INTERVAL | – | 时间间隔 | INTERVAL '1' DAY |
7.2 复杂数据类型
| ARRAY | ARRAY<data_type> | 有序列表,下标从 0 开始 | ['a','b','c'] |
| MAP | MAP<key_type, val_type> | 键值对,key 必须是基本类型 | {'k1':1,'k2':2} |
| STRUCT | STRUCT<name:type,…> | 命名字段的结构体 | {'name':'Alice','age':30} |
| UNIONTYPE | UNIONTYPE<t1,t2,…> | 联合类型(较少使用) | – |
— 复杂类型的使用示例
CREATE TABLE complex_example (
id INT,
tags ARRAY<STRING>, — 数组
props MAP<STRING, STRING>, — Map
address STRUCT<city:STRING, zip:STRING, country:STRING> — 结构体
);
— 插入复杂类型数据
INSERT INTO complex_example VALUES (
1,
ARRAY('hive', 'hadoop', 'spark'),
MAP('color', 'blue', 'size', 'L'),
NAMED_STRUCT('city', 'Beijing', 'zip', '100000', 'country', 'CN')
);
— 访问复杂类型
SELECT
id,
tags[0] AS first_tag, — 数组下标访问
tags[1] AS second_tag,
SIZE(tags) AS tag_count, — 数组大小
props['color'] AS color, — Map 键访问
address.city AS city, — Struct 字段访问
address.zip AS zip
FROM complex_example;
— EXPLODE 展开数组
SELECT id, tag
FROM complex_example
LATERAL VIEW EXPLODE(tags) tmp AS tag;
— EXPLODE 展开 Map
SELECT id, k, v
FROM complex_example
LATERAL VIEW EXPLODE(props) tmp AS k, v;
7.3 类型转换
— 隐式转换(自动类型提升:TINYINT → SMALLINT → INT → BIGINT → FLOAT → DOUBLE)
SELECT 1 + 1.5; — 自动转为 DOUBLE
— 显式转换(CAST)
SELECT CAST('123' AS INT);
SELECT CAST(3.14 AS INT); — 截断 → 3
SELECT CAST('2024-01-01' AS DATE);
SELECT CAST(salary AS STRING) FROM employees;
— 字符串与数字转换
SELECT CAST('123abc' AS INT); — 返回 NULL(无法转换)
— 日期类型转换
SELECT TO_DATE('2024-01-15 12:30:00'); — → '2024-01-15'
SELECT UNIX_TIMESTAMP('2024-01-01 00:00:00', 'yyyy-MM-dd HH:mm:ss'); — → 秒级时间戳
SELECT FROM_UNIXTIME(1704067200, 'yyyy-MM-dd HH:mm:ss'); — 时间戳 → 字符串
8. Hive 文件格式与存储
8.1 支持的文件格式对比
| TextFile | 行式,纯文本 | gzip/bzip2 等 | 差 | 快 | 数据交换、调试、原始日志 |
| SequenceFile | 行式,二进制 | Block/Record | 一般 | 一般 | Hadoop 原生,历史遗留 |
| RCFile | 列式,行组 | 支持 | 中等 | 一般 | 旧系统 |
| ORC | 列式(带索引) | Zlib/Snappy/LZ4 | 极好 | 中等 | 生产推荐:分析型查询 |
| Parquet | 列式 | Gzip/Snappy/LZ4 | 极好 | 中等 | 生产推荐:与 Spark 互通 |
| Avro | 行式,带 Schema | Deflate/Snappy | 中等 | 快 | 数据序列化、Kafka 数据落地 |
8.2 ORC 格式详解(推荐)
ORC(Optimized Row Columnar)是 Hive 原生的高性能列式文件格式:
ORC 文件结构:
ORC 文件
├── Stripe 1(默认 64MB)
│ ├── Index Data(轻量级索引,每 10000 行一个)
│ ├── Row Data(实际列数据)
│ └── Stripe Footer(列统计信息)
├── Stripe 2
│ └── …
└── File Footer
├── 文件级统计信息(行数、列最大/最小值等)
└── Stripe 位置信息
ORC 的核心优化:
- 列投影(Column Projection):只读取查询涉及的列
- 谓词下推(Predicate Pushdown):利用 Stripe/Row Group 统计信息跳过无关数据
- Bloom Filter 索引:快速判断某个 Stripe 是否包含目标值
- Run-Length Encoding(RLE):对整数列压缩效果极好
- Dictionary Encoding:对低基数字符串列压缩率极高
— 使用 ORC 格式建表
CREATE TABLE sales (
sale_id BIGINT,
product STRING,
amount DECIMAL(12,2),
sale_date DATE
)
STORED AS ORC
TBLPROPERTIES (
'orc.compress'='SNAPPY', — 压缩算法:NONE/ZLIB/SNAPPY/LZ4(推荐 SNAPPY)
'orc.stripe.size'='67108864', — Stripe 大小 64MB
'orc.row.index.stride'='10000', — 行组索引步长
'orc.create.index'='true' — 启用行组索引
);
— 将 TextFile 表转换为 ORC
CREATE TABLE sales_orc STORED AS ORC AS SELECT * FROM sales_text;
8.3 Parquet 格式详解
Parquet 是跨语言的通用列式格式,与 Spark、Impala、Presto 互通性最好:
— 使用 Parquet 建表
CREATE TABLE events_parquet (
event_id STRING,
user_id BIGINT,
event_type STRING,
ts TIMESTAMP
)
STORED AS PARQUET
TBLPROPERTIES (
'parquet.compression'='SNAPPY' — UNCOMPRESSED/GZIP/SNAPPY/LZO/BROTLI/LZ4
);
8.4 压缩配置
— 开启中间结果(Map 输出)压缩
SET hive.exec.compress.intermediate=true;
SET mapreduce.map.output.compress=true;
SET mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;
— 开启最终输出压缩
SET hive.exec.compress.output=true;
SET mapreduce.output.fileoutputformat.compress=true;
SET mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;
SET mapreduce.output.fileoutputformat.compress.type=BLOCK;
— Tez 引擎中间数据压缩
SET tez.runtime.compress=true;
SET tez.runtime.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;
9. SerDe(Serialization / Deserialization)
SerDe 是 Hive 读写文件的核心接口,决定了 Hive 如何解析和序列化数据。
9.1 常用内置 SerDe
LazySimpleSerDe(默认)
— 解析分隔符文本
CREATE TABLE csv_data (
id INT,
name STRING,
age INT
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
'field.delim'=',',
'line.delim'='\\n',
'null.format'='\\\\N'
)
STORED AS TEXTFILE;
— 简写方式(等价于上面)
CREATE TABLE csv_data2 (id INT, name STRING, age INT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\\n'
NULL DEFINED AS '\\\\N'
STORED AS TEXTFILE;
JsonSerDe
— 解析 JSON 格式文件(每行一个 JSON)
CREATE TABLE json_logs (
user_id INT,
action STRING,
timestamp BIGINT,
metadata MAP<STRING, STRING>
)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
STORED AS TEXTFILE;
RegexSerDe(正则表达式)
— 用正则表达式解析复杂格式(如 Apache 日志)
CREATE TABLE apache_logs (
ip STRING,
identity STRING,
user STRING,
time STRING,
request STRING,
status INT,
size INT
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
'input.regex' = '([^ ]*) ([^ ]*) ([^ ]*) \\\\[([^\\\\]]*)\\\\] "([^"]*)" ([0-9]*) ([0-9]*)'
)
STORED AS TEXTFILE;
OpenCSVSerde
— 处理包含转义字符的复杂 CSV
CREATE TABLE complex_csv (
id STRING,
name STRING,
desc STRING
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (
'separatorChar'=',',
'quoteChar'='"',
'escapeChar'='\\\\'
)
STORED AS TEXTFILE;
10. Hive 内置函数大全
10.1 字符串函数
— 基本操作
SELECT LENGTH('hello world'); — 11
SELECT LOWER('Hello WORLD'); — hello world
SELECT UPPER('hello world'); — HELLO WORLD
SELECT TRIM(' hello '); — hello
SELECT LTRIM(' hello '); — 'hello '
SELECT RTRIM(' hello '); — ' hello'
— 截取与拼接
SELECT SUBSTR('hello world', 1, 5); — hello(下标从 1 开始)
SELECT SUBSTRING('hello world', 7); — world
SELECT CONCAT('hello', ' ', 'world'); — hello world
SELECT CONCAT_WS('-', 'a', 'b', 'c'); — a-b-c(带分隔符)
— 查找与替换
SELECT INSTR('hello world', 'world'); — 7(位置)
SELECT LOCATE('world', 'hello world'); — 7
SELECT REPLACE('hello world', 'world', 'hive'); — hello hive
SELECT REGEXP_REPLACE('abc123def', '[0-9]+', 'NUM'); — abcNUMdef
SELECT REGEXP_EXTRACT('abc123def', '[0-9]+', 0); — 123
— 分割与拼接
SELECT SPLIT('a,b,c', ','); — ["a","b","c"](返回数组)
SELECT SPLIT('a,b,c', ',')[1]; — b(取第2个)
— 格式化
SELECT LPAD('5', 4, '0'); — 0005(左填充)
SELECT RPAD('5', 4, '0'); — 5000(右填充)
SELECT PRINTF('%05d', 42); — 00042
SELECT FORMAT_NUMBER(1234567.89, 2); — 1,234,567.89
— 字符串判断
SELECT LIKE('hello', 'hel%'); — true
SELECT RLIKE('hello123', '[a-z]+[0-9]+'); — true
— 其他
SELECT REVERSE('hello'); — olleh
SELECT REPEAT('ab', 3); — ababab
SELECT SPACE(5); — ' '(5 个空格)
SELECT ASCII('A'); — 65
SELECT CHR(65); — A
SELECT QUOTE('it''s'); — 'it\\'s'
SELECT INITCAP('hello world'); — Hello World
10.2 数学函数
SELECT ROUND(3.567, 2); — 3.57
SELECT FLOOR(3.7); — 3
SELECT CEIL(3.2); — 4
SELECT ABS(–5); — 5
SELECT SQRT(16); — 4.0
SELECT POWER(2, 10); — 1024.0
SELECT LOG(10, 100); — 2.0(log 以 10 为底)
SELECT LN(2.718281); — ≈1.0
SELECT EXP(1); — ≈2.718
SELECT MOD(10, 3); — 1
SELECT SIGN(–5); — -1(正数1,负数-1,零0)
SELECT PI(); — 3.141592653589793
SELECT SIN(0), COS(0), TAN(0); — 0.0, 1.0, 0.0
SELECT RAND(); — 0~1 随机数
SELECT RAND(42); — 固定种子的随机数
SELECT GREATEST(3, 1, 4, 1, 5, 9); — 9
SELECT LEAST(3, 1, 4, 1, 5, 9); — 1
SELECT FACTORIAL(5); — 120
SELECT SHIFTLEFT(8, 2); — 32(位运算左移)
SELECT SHIFTRIGHT(32, 2); — 8(位运算右移)
SELECT HEX(255); — FF
SELECT UNHEX('FF'); — 255
10.3 日期和时间函数
— 获取当前时间
SELECT CURRENT_DATE(); — 2024-01-01
SELECT CURRENT_TIMESTAMP(); — 2024-01-01 12:00:00.000
SELECT NOW(); — 等价于 CURRENT_TIMESTAMP()
SELECT UNIX_TIMESTAMP(); — 当前 Unix 时间戳(秒)
— 日期解析与格式化
SELECT TO_DATE('2024-01-15 12:30:00'); — 2024-01-15
SELECT DATE_FORMAT('2024-01-15', 'yyyyMMdd'); — 20240115
SELECT UNIX_TIMESTAMP('2024-01-01', 'yyyy-MM-dd'); — → 1704067200
SELECT FROM_UNIXTIME(1704067200); — 2024-01-01 00:00:00
SELECT FROM_UNIXTIME(1704067200, 'yyyy-MM-dd'); — 2024-01-01
— 日期提取
SELECT YEAR('2024-01-15'); — 2024
SELECT MONTH('2024-01-15'); — 1
SELECT DAY('2024-01-15'); — 15
SELECT HOUR('2024-01-15 12:30:45'); — 12
SELECT MINUTE('2024-01-15 12:30:45'); — 30
SELECT SECOND('2024-01-15 12:30:45'); — 45
SELECT WEEKOFYEAR('2024-01-15'); — 3(第3周)
SELECT DAYOFWEEK('2024-01-15'); — 2(1=周日,2=周一…)
SELECT QUARTER('2024-04-15'); — 2
— 日期运算
SELECT DATE_ADD('2024-01-15', 10); — 2024-01-25
SELECT DATE_SUB('2024-01-15', 10); — 2024-01-05
SELECT DATEDIFF('2024-01-15', '2024-01-01'); — 14(天数差)
SELECT ADD_MONTHS('2024-01-15', 2); — 2024-03-15
SELECT LAST_DAY('2024-02-01'); — 2024-02-29(当月最后一天)
SELECT NEXT_DAY('2024-01-15', 'Monday'); — 下一个星期一
— 日期截断
SELECT TRUNC('2024-01-15', 'MM'); — 2024-01-01(月初)
SELECT TRUNC('2024-01-15', 'YY'); — 2024-01-01(年初)
SELECT DATE_TRUNC('month', '2024-01-15 12:30:00'); — 2024-01-01 00:00:00
— 日期比较
SELECT GREATEST('2024-01-15', '2023-12-31'); — 2024-01-15
10.4 条件函数
— NVL / COALESCE(空值处理)
SELECT NVL(NULL, 'default'); — default
SELECT NVL(null_col, 0) FROM table; — 替换 NULL 为 0
SELECT COALESCE(a, b, c, 'none'); — 返回第一个非 NULL 值
— IF
SELECT IF(salary > 10000, '高薪', '低薪') FROM employees;
— IFF(Hive 2.0+)
SELECT IFF(score >= 60, 'pass', 'fail') FROM students;
— NULLIF(相等则返回 NULL)
SELECT NULLIF(a, b); — 若 a=b 则返回 NULL,否则返回 a
— CASE WHEN(见查询章节)
— ISNULL / ISNOTNULL
SELECT ISNULL(null_col) FROM table; — true/false
— NVL2
SELECT NVL2(email, '有邮箱', '无邮箱') FROM employees;
— DECODE(Oracle 兼容)
SELECT DECODE(status, 1, '有效', 0, '无效', '未知') FROM orders;
10.5 聚合函数
SELECT
COUNT(*) AS total_rows,
COUNT(email) AS non_null_emails, — 不统计 NULL
COUNT(DISTINCT dept) AS unique_depts,
SUM(salary) AS total_salary,
AVG(salary) AS avg_salary,
MAX(salary) AS max_salary,
MIN(salary) AS min_salary,
STDDEV_POP(salary) AS std_salary, — 标准差(总体)
VARIANCE(salary) AS var_salary, — 方差
COLLECT_SET(dept) AS dept_set, — 收集唯一值到数组
COLLECT_LIST(dept) AS dept_list, — 收集所有值到数组(含重复)
PERCENTILE(salary, 0.5) AS median, — 中位数(数值列)
PERCENTILE_APPROX(salary, 0.5) AS approx_median — 近似中位数(大数据)
FROM employees;
— GROUP_CONCAT(类似 MySQL 的 GROUP_CONCAT)
SELECT dept, CONCAT_WS(',', COLLECT_LIST(name)) AS member_names
FROM employees
GROUP BY dept;
— GROUPING SETS / CUBE / ROLLUP(多维聚合)
— ROLLUP(层级聚合,等于多个 GROUP BY 结果的 UNION)
SELECT dept, job_level, SUM(salary)
FROM employees
GROUP BY dept, job_level WITH ROLLUP;
— CUBE(所有维度组合)
SELECT dept, year, SUM(salary)
FROM employees
GROUP BY dept, year WITH CUBE;
— GROUPING SETS(指定聚合维度)
SELECT dept, country, SUM(salary)
FROM employees
GROUP BY dept, country
GROUPING SETS ((dept, country), (dept), (country), ());
10.6 集合函数
SELECT
SIZE(tags) AS tag_count, — 数组/Map 的大小
ARRAY_CONTAINS(tags, 'hadoop') AS has_hadoop, — 是否包含元素
SORT_ARRAY(tags) AS sorted_tags, — 数组排序
ARRAY_MIN(scores) AS min_score,
ARRAY_MAX(scores) AS max_score,
MAP_KEYS(props) AS prop_keys, — Map 的键列表
MAP_VALUES(props) AS prop_values, — Map 的值列表
STR_TO_MAP('a:1,b:2', ',', ':') AS prop_map — 字符串转 Map
FROM complex_table;
11. 用户自定义函数(UDF / UDAF / UDTF)
11.1 三类自定义函数对比
| UDF | User Defined Function | 一行输入 → 一行输出(1:1) | UPPER(), LENGTH() | 字段转换、计算 |
| UDAF | User Defined Aggregate Function | 多行输入 → 一行输出(N:1) | COUNT(), SUM() | 自定义聚合计算 |
| UDTF | User Defined Table-Generating Function | 一行输入 → 多行输出(1:N) | EXPLODE(), JSON_TUPLE() | 行展开、数组拆分 |
11.2 编写简单 UDF
// 示例:将字符串中的手机号脱敏(替换中间4位为****)
package com.example.hive.udf;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;
@Description(
name = "mask_phone",
value = "_FUNC_(phone) – Masks the middle 4 digits of phone number",
extended = "Example: SELECT mask_phone('13812345678') FROM dual;"
)
public class MaskPhoneUDF extends UDF {
public Text evaluate(Text phone) {
if (phone == null) return null;
String phoneStr = phone.toString();
if (phoneStr.length() != 11) return phone;
return new Text(phoneStr.substring(0, 3) + "****" + phoneStr.substring(7));
}
// 方法重载:处理多种输入类型
public String evaluate(String phone) {
if (phone == null || phone.length() != 11) return phone;
return phone.substring(0, 3) + "****" + phone.substring(7);
}
}
# 编译打包(Maven 方式)
mvn clean package -DskipTests
# 生成 target/my-hive-udf.jar
— 在 Hive 中注册并使用 UDF
— 方式1:临时函数(当前会话有效)
ADD JAR hdfs:///jars/my-hive-udf.jar;
CREATE TEMPORARY FUNCTION mask_phone AS 'com.example.hive.udf.MaskPhoneUDF';
— 方式2:永久函数(写入 Metastore,所有会话可用)
— 需先将 JAR 上传到 HDFS
CREATE FUNCTION mydb.mask_phone AS 'com.example.hive.udf.MaskPhoneUDF'
USING JAR 'hdfs:///jars/my-hive-udf.jar';
— 使用自定义函数
SELECT user_id, mask_phone(phone) AS masked_phone FROM users;
— 查看已注册函数
SHOW FUNCTIONS LIKE 'mask*';
DESCRIBE FUNCTION mask_phone;
DESCRIBE FUNCTION EXTENDED mask_phone;
— 删除函数
DROP TEMPORARY FUNCTION mask_phone;
DROP FUNCTION IF EXISTS mydb.mask_phone;
11.3 编写 GenericUDF(支持复杂类型)
// GenericUDF:支持数组、Map、Struct 等复杂类型
package com.example.hive.udf;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;
@Description(name = "to_upper", value = "_FUNC_(str) – converts string to uppercase")
public class ToUpperGenericUDF extends GenericUDF {
private StringObjectInspector stringOI;
@Override
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
if (arguments.length != 1) {
throw new UDFArgumentException("to_upper takes exactly one argument");
}
if (!(arguments[0] instanceof StringObjectInspector)) {
throw new UDFArgumentTypeException(0, "to_upper argument must be a string");
}
this.stringOI = (StringObjectInspector) arguments[0];
return PrimitiveObjectInspectorFactory.javaStringObjectInspector; // 返回类型
}
@Override
public Object evaluate(DeferredObject[] arguments) throws HiveException {
String input = stringOI.getPrimitiveJavaObject(arguments[0].get());
if (input == null) return null;
return input.toUpperCase();
}
@Override
public String getDisplayString(String[] children) {
return "to_upper(" + children[0] + ")";
}
}
11.4 编写 UDAF
// UDAF:统计字符串列中字符总长度
package com.example.hive.udaf;
import org.apache.hadoop.hive.ql.exec.UDAF;
import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
public class TotalLengthUDAF extends UDAF {
public static class TotalLengthEvaluator implements UDAFEvaluator {
private long total = 0;
@Override
public void init() { total = 0; }
// 处理每行输入
public boolean iterate(Text input) {
if (input != null) total += input.getLength();
return true;
}
// 返回部分聚合结果(Map 端输出)
public LongWritable terminatePartial() {
return new LongWritable(total);
}
// 合并部分结果(Reduce 端合并)
public boolean merge(LongWritable partial) {
if (partial != null) total += partial.get();
return true;
}
// 返回最终结果
public LongWritable terminate() {
return new LongWritable(total);
}
}
}
11.5 编写 UDTF
// UDTF:将 CSV 字符串拆分为多行
package com.example.hive.udtf;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.*;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import java.util.ArrayList;
public class SplitToRowsUDTF extends GenericUDTF {
private PrimitiveObjectInspector stringOI;
@Override
public StructObjectInspector initialize(ObjectInspector[] argOIs) throws UDFArgumentException {
// 定义输出列
List<String> fieldNames = new ArrayList<>();
List<ObjectInspector> fieldOIs = new ArrayList<>();
fieldNames.add("value");
fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
this.stringOI = (PrimitiveObjectInspector) argOIs[0];
return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);
}
@Override
public void process(Object[] args) throws HiveException {
String input = (String) stringOI.getPrimitiveJavaObject(args[0]);
if (input != null) {
String[] parts = input.split(",");
for (String part : parts) {
forward(new Object[]{part.trim()}); // 每个元素输出一行
}
}
}
@Override
public void close() throws HiveException {}
}
— 使用 UDTF
CREATE TEMPORARY FUNCTION split_to_rows AS 'com.example.hive.udtf.SplitToRowsUDTF'
USING JAR 'hdfs:///jars/my-hive-udf.jar';
— 直接使用
SELECT split_to_rows(tag_str) AS tag FROM raw_data;
— 配合 LATERAL VIEW 使用
SELECT id, tag
FROM raw_data
LATERAL VIEW split_to_rows(tag_str) tmp AS tag;
12. Hive 执行引擎
12.1 三种执行引擎对比
| 计算模型 | Map + Reduce(两阶段) | DAG(任意拓扑) | DAG + 内存 RDD |
| 中间结果 | 写磁盘 HDFS | 写磁盘(可内存缓冲) | 内存(可 spill 磁盘) |
| 延迟 | 高(秒~分钟) | 中(亚秒~秒) | 低(亚秒) |
| 复杂查询 | 多个 MR job,效率低 | 一个 DAG,高效 | 极高效 |
| 容错 | Task 级重试 | 同 MR | RDD 血缘重算 |
| 成熟度 | 最高 | 高(Hive 推荐) | 高 |
| Hive 推荐版本 | Hive 1.x 默认 | Hive 2.x+ 推荐 | Hive on Spark |
12.2 切换执行引擎
— 查看当前执行引擎
SET hive.execution.engine;
— 切换到 Tez(推荐,绝大多数生产环境)
SET hive.execution.engine=tez;
— 切换到 Spark
SET hive.execution.engine=spark;
— 切换回 MapReduce
SET hive.execution.engine=mr;
12.3 LLAP(Live Long and Process)
LLAP 是 Hive 2.0 引入的交互式查询加速功能:
传统模式:提交查询 → 启动 JVM → 加载数据 → 执行 → 销毁 JVM(每次都有冷启动开销)
LLAP 模式:常驻的 Daemon 进程 → 缓存热数据(行列缓存) → 亚秒级响应
LLAP 核心特性:
- 持久化的 Daemon(避免 JVM 冷启动)
- 行列缓存(将 ORC/Parquet 热数据块缓存在内存)
- 细粒度资源弹性(可根据负载动态调整)
- 支持并发查询
— 启用 LLAP(需要先部署 LLAP Daemons)
SET hive.llap.execution.mode = auto;
— 在 hive-site.xml 中配置
— hive.llap.daemon.memory.per.instance.mb=4096
— hive.llap.daemon.vcpus.per.instance=4
— hive.llap.io.enabled=true
13. Hive 性能调优
13.1 小文件合并
Hive 中小文件是最常见的性能问题之一,大量小文件会严重拖慢 NameNode 和 MapReduce 任务:
— 方式1:查询时合并小文件(Map-Only 任务)
SET hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
SET mapreduce.input.fileinputformat.split.minsize=134217728; — 128MB
SET mapreduce.input.fileinputformat.split.maxsize=268435456; — 256MB
— 方式2:输出时合并小文件
SET hive.merge.mapfiles=true; — 合并 Map-Only 任务输出
SET hive.merge.mapredfiles=true; — 合并 MapReduce 任务输出
SET hive.merge.size.per.task=268435456; — 目标合并文件大小 256MB
SET hive.merge.smallfiles.avgsize=134217728; — 触发合并的平均文件大小阈值
— 方式3:定期手动合并(ORC 格式)
ALTER TABLE user_events PARTITION (dt='2024-01-01') CONCATENATE;
— 方式4:Spark 重写(最彻底的方式)
INSERT OVERWRITE TABLE t PARTITION(dt='2024-01-01')
SELECT * FROM t WHERE dt='2024-01-01';
13.2 分区裁剪优化
— ❌ 错误:分区条件在函数内,无法裁剪
SELECT * FROM user_events WHERE YEAR(dt) = 2024 AND MONTH(dt) = 1;
— ✅ 正确:直接在分区列上使用字符串比较
SELECT * FROM user_events WHERE dt BETWEEN '2024-01-01' AND '2024-01-31';
SELECT * FROM user_events WHERE dt >= '2024-01-01' AND dt < '2024-02-01';
— 验证分区裁剪是否生效
EXPLAIN SELECT * FROM user_events WHERE dt = '2024-01-01';
— 在执行计划中查找 "partition filter"
— 强制分区过滤(防止全表扫描)
SET hive.mapred.mode=strict; — 查询分区表时必须有分区条件,否则报错
13.3 MapJoin(小表 JOIN 优化)
— 自动 MapJoin(Hive 自动判断小表)
SET hive.auto.convert.join=true; — 默认 true
SET hive.mapjoin.smalltable.filesize=25000000; — 小表阈值:25MB
SET hive.auto.convert.join.noconditionaltask=true;
SET hive.auto.convert.join.noconditionaltask.size=10000000; — 10MB
— 手动指定 MapJoin(HINT 方式)
SELECT /*+ MAPJOIN(d) */ e.name, d.dept_name
FROM employees e JOIN departments d ON e.dept_id = d.id;
— Bucket Map Join(两表按相同列分桶,且桶数相同)
SET hive.optimize.bucketmapjoin=true;
SET hive.optimize.bucketmapjoin.sortedmerge=true; — SMB Join(最高效)
13.4 数据倾斜处理
数据倾斜是导致 Hive 作业长时间卡在 99% 的最常见原因。
— 1. 开启倾斜 Join 优化
SET hive.optimize.skewjoin=true;
SET hive.skewjoin.key=100000; — 超过 10 万行认为是热点 key
— 2. 随机前缀法(解决 GROUP BY 热点 key)
— 第一步:加随机前缀,拆散热点 key
SELECT CONCAT(FLOOR(RAND() * 100), '_', user_id) AS rkey,
SUM(amount) AS partial_sum
FROM orders GROUP BY CONCAT(FLOOR(RAND() * 100), '_', user_id);
— 第二步:去掉前缀,再次聚合
SELECT SPLIT(rkey, '_')[1] AS user_id, SUM(partial_sum)
FROM (上面的子查询) t GROUP BY SPLIT(rkey, '_')[1];
— 3. 过滤 NULL Key(NULL JOIN 时会全部分到同一 Reducer)
SELECT e.*, d.*
FROM employees e
JOIN departments d ON e.dept_id IS NOT NULL AND e.dept_id = d.id;
— 4. 两阶段聚合(Map 端预聚合)
SET hive.map.aggr=true; — 开启 Map 端聚合(默认开启)
SET hive.groupby.skewindata=true; — 倾斜数据随机分发到 Reducer(两次 MR)
13.5 Tez 引擎调优
— Tez 容器大小(AM 和 Task 都用这个)
SET tez.am.resource.memory.mb=1024;
SET tez.task.resource.memory.mb=2048;
SET tez.task.launch.cmd–opts=–Xmx1800m;
— 关闭 Tez Session(按需启动,节省资源)
SET tez.session.am.dag.submit.timeout.secs=600;
— 开启预取优化
SET tez.runtime.enable.final–merge.in.output=true;
— 增加并行度
SET hive.exec.parallel=true; — 允许并行执行多个 Stage
SET hive.exec.parallel.thread.number=8; — 最大并行线程数
13.6 CBO(基于代价的优化器)
— 启用 CBO(需要先收集统计信息)
SET hive.cbo.enable=true; — 默认 true(Hive 0.14+)
SET hive.compute.query.using.stats=true;
SET hive.stats.fetch.column.stats=true;
SET hive.stats.fetch.partition.stats=true;
— 收集统计信息(建议定期对重要表执行)
ANALYZE TABLE employees COMPUTE STATISTICS; — 表级别统计
ANALYZE TABLE employees COMPUTE STATISTICS FOR COLUMNS; — 列级别统计
ANALYZE TABLE user_events PARTITION (dt='2024-01-01') COMPUTE STATISTICS;
— 查看统计信息
DESCRIBE FORMATTED employees; — 在输出中找 numRows、totalSize
— 在 hive-site.xml 中启用自动统计收集
— hive.stats.autogather=true (INSERT/LOAD 后自动更新)
13.7 向量化执行
— 开启向量化执行(一次处理 1024 行,利用 CPU SIMD 指令)
SET hive.vectorized.execution.enabled=true; — 默认 true(Hive 0.13+)
SET hive.vectorized.execution.reduce.enabled=true;
SET hive.vectorized.execution.reduce.groupby.enabled=true;
— 查看向量化是否生效
EXPLAIN VECTORIZATION SELECT * FROM employees;
13.8 常见性能配置汇总
— 一次性优化配置(可放入 hive-site.xml 或每次 Session 开始时执行)
SET hive.execution.engine=tez;
SET hive.auto.convert.join=true;
SET hive.cbo.enable=true;
SET hive.compute.query.using.stats=true;
SET hive.exec.parallel=true;
SET hive.exec.parallel.thread.number=8;
SET hive.vectorized.execution.enabled=true;
SET hive.exec.dynamic.partition=true;
SET hive.exec.dynamic.partition.mode=nonstrict;
SET hive.merge.mapfiles=true;
SET hive.merge.mapredfiles=true;
SET hive.merge.size.per.task=256000000;
SET hive.map.aggr=true;
SET hive.groupby.skewindata=true;
SET hive.exec.compress.intermediate=true;
SET hive.exec.compress.output=true;
14. Hive 分区管理深入
14.1 静态分区 vs 动态分区
| 分区值 | 手动指定 | 查询时自动从数据中提取 |
| 速度 | 快(无需扫描分区列) | 较慢(需要额外 Reducer) |
| 使用场景 | 已知分区值,如按日期加载 | 分区值多或未知 |
| 语法 | PARTITION (dt='2024-01-01') | PARTITION (dt) |
— 静态分区
INSERT INTO TABLE user_events PARTITION (dt='2024-01-01', country='CN')
SELECT user_id, event_type, event_time, page_url
FROM raw_events_20240101;
— 动态分区(分区列放在 SELECT 最后)
SET hive.exec.dynamic.partition=true;
SET hive.exec.dynamic.partition.mode=nonstrict;
SET hive.exec.max.dynamic.partitions=1000; — 最大动态分区数
SET hive.exec.max.dynamic.partitions.pernode=300; — 每节点最大动态分区数
INSERT OVERWRITE TABLE user_events PARTITION (dt, country)
SELECT user_id, event_type, event_time, page_url, dt, country — dt 和 country 在最后
FROM raw_events;
14.2 分区命名规范建议
— 推荐:字符串分区键,格式一致
PARTITIONED BY (dt STRING COMMENT 'date partition, format: yyyyMMdd')
— 推荐:多级分区,粗粒度在前
PARTITIONED BY (year STRING, month STRING, day STRING)
— 注意:分区值本身不存储在数据文件中,只体现在目录名中
— 不建议将高基数列(如 user_id)作为分区键,会产生大量小文件
14.3 分区维护
— 检查并修复分区(HDFS 目录存在但 Metastore 无记录)
MSCK REPAIR TABLE user_events;
— 检查分区完整性
SHOW PARTITIONS user_events;
— 查看特定分区的详情
DESCRIBE FORMATTED user_events PARTITION (dt='2024-01-01');
— 交换分区(在两张相同结构的表间快速移动分区数据)
ALTER TABLE user_events EXCHANGE PARTITION (dt='2024-01-01') WITH TABLE user_events_staging;
— 截断分区(仅清空数据,保留分区元数据)
TRUNCATE TABLE user_events PARTITION (dt='2023-01-01');
— 归档分区(压缩为 Hadoop Archive 文件,减少小文件数量)
SET hive.archive.enabled=true;
ALTER TABLE user_events ARCHIVE PARTITION (dt='2023-01-01');
ALTER TABLE user_events UNARCHIVE PARTITION (dt='2023-01-01');
15. Hive 元数据服务(Metastore)
15.1 Metastore 三种部署模式
嵌入式模式(Embedded)
Hive CLI ─── Driver ─── Metastore API ─── Derby(嵌入式数据库)
- Derby 数据库随 Hive 进程一起启动
- 只支持单连接
- 仅适合学习和测试
本地模式(Local)
Hive CLI ─── Driver ─── Metastore API ─── MySQL(同机)
- Metastore 在 Hive 进程内运行,但使用外部 MySQL
- 支持多连接,但每个 Hive 进程都直接连接数据库
- 适合小型集群
远程模式(Remote,生产推荐)
Hive Client 1 ─┐
Hive Client 2 ─┼─── Thrift Server ─── Metastore API ─── MySQL
Spark/Impala ──┘ (9083 端口)
- Metastore 作为独立服务运行
- 所有客户端通过 Thrift 协议连接
- 支持多客户端并发
- 数据库连接由 Metastore 服务统一管理
15.2 Metastore 重要配置
<!– 元数据服务地址 –>
<property>
<name>hive.metastore.uris</name>
<value>thrift://metastore-host:9083</value>
</property>
<!– 元数据库连接池配置 –>
<property>
<name>datanucleus.connectionPoolingType</name>
<value>DBCP</value>
</property>
<property>
<name>datanucleus.connectionPool.maxPoolSize</name>
<value>20</value>
</property>
<!– 开启元数据缓存(减少 DB 查询) –>
<property>
<name>hive.metastore.cache.pinobjtypes</name>
<value>Table,StorageDescriptor,SerDeInfo,Partition,Database,Type,FieldSchema,Order</value>
</property>
<!– Schema 版本兼容性检查 –>
<property>
<name>hive.metastore.schema.verification</name>
<value>true</value>
</property>
15.3 Metastore HA(高可用)
<!– 配置多个 Metastore 实例实现高可用 –>
<property>
<name>hive.metastore.uris</name>
<value>thrift://metastore1:9083,thrift://metastore2:9083</value>
</property>
在多个节点上分别启动 Metastore 服务:
hive –service metastore & # 在 metastore1 上
hive –service metastore & # 在 metastore2 上
16. HiveServer2 与 Beeline
16.1 HiveServer2(HS2)
HiveServer2 是 Hive 提供远程多并发客户端访问的服务:
核心特性:
- 多并发:支持多个客户端同时连接(HiveServer1 不支持)
- 认证:Kerberos、LDAP、自定义认证
- JDBC/ODBC 接口:标准 JDBC(端口 10000)
- Web UI:默认 10002 端口,可监控 Sessions 和 Queries
# 启动 HiveServer2
hive –service hiveserver2 &
# 或者(推荐,重定向日志)
nohup $HIVE_HOME/bin/hiveserver2 > /var/log/hive/hiveserver2.log 2>&1 &
# 查看 Web UI
http://localhost:10002
16.2 Beeline 使用详解
Beeline 是基于 JDBC 的 HiveServer2 客户端,推荐替代旧的 Hive CLI:
# 连接方式1:本地连接(不需要认证)
beeline -u jdbc:hive2://localhost:10000
# 连接方式2:指定用户名密码
beeline -u jdbc:hive2://localhost:10000 -n hive -p password
# 连接方式3:Kerberos 认证
beeline -u "jdbc:hive2://localhost:10000/default;principal=hive/hostname@REALM"
# 连接方式4:指定数据库
beeline -u jdbc:hive2://localhost:10000/mydb
# 非交互式:执行单个查询后退出
beeline -u jdbc:hive2://localhost:10000 -e "SELECT COUNT(*) FROM employees"
# 非交互式:执行 SQL 脚本文件
beeline -u jdbc:hive2://localhost:10000 -f /path/to/script.hql
# 关闭 beeline header 和 footer(适合脚本解析)
beeline –silent=true –outputformat=tsv2 -u jdbc:hive2://localhost:10000 \\
-e "SELECT * FROM employees" > output.tsv
Beeline 交互式命令:
— 连接到 HiveServer2
!connect jdbc:hive2://localhost:10000
— 断开连接
!disconnect
— 退出
!quit
— 查看所有命令
!help
— 查看当前连接信息
!info
— 执行 Shell 命令
!sh ls /data/
— 查看历史命令
!history
— 设置输出格式
!set outputformat table — 表格(默认)
!set outputformat csv2 — CSV
!set outputformat tsv2 — TSV
!set outputformat json — JSON
— 显示/隐藏列 Header
!set headerInterval 0 — 只显示一次 Header
!set showHeader true/false
— 设置最大行宽
!set maxWidth 200
!set maxColumnWidth 50
16.3 JDBC 程序连接 Hive
import java.sql.*;
public class HiveJDBCExample {
private static final String JDBC_URL = "jdbc:hive2://localhost:10000/default";
private static final String DRIVER_CLASS = "org.apache.hive.jdbc.HiveDriver";
public static void main(String[] args) throws Exception {
Class.forName(DRIVER_CLASS);
try (Connection conn = DriverManager.getConnection(JDBC_URL, "hive", "");
Statement stmt = conn.createStatement()) {
// 创建表
stmt.execute("CREATE TABLE IF NOT EXISTS test_jdbc (id INT, name STRING) STORED AS ORC");
// 插入数据
stmt.execute("INSERT INTO test_jdbc VALUES (1, 'Alice'), (2, 'Bob')");
// 查询
try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_jdbc")) {
ResultSetMetaData metaData = rs.getMetaData();
while (rs.next()) {
for (int i = 1; i <= metaData.getColumnCount(); i++) {
System.out.print(rs.getString(i) + "\\t");
}
System.out.println();
}
}
}
}
}
Maven 依赖:
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>3.1.3</version>
</dependency>
17. Hive 安全机制
17.1 认证方式
| 无认证 | 开发/测试 | 默认 |
| LDAP | 企业 Active Directory 集成 | hive.server2.authentication=LDAP |
| Kerberos | 企业生产安全环境 | hive.server2.authentication=KERBEROS |
| Custom | 自定义认证插件 | hive.server2.authentication=CUSTOM |
| PAM | Linux PAM 认证 | hive.server2.authentication=PAM |
<!– Kerberos 认证配置示例 –>
<property>
<name>hive.server2.authentication</name>
<value>KERBEROS</value>
</property>
<property>
<name>hive.server2.kerberos.principal</name>
<value>hive/_HOST@YOUR-REALM.COM</value>
</property>
<property>
<name>hive.server2.kerberos.keytab</name>
<value>/etc/security/keytabs/hive.service.keytab</value>
</property>
17.2 授权机制
— Hive 内置权限控制(基于 SQL 标准)
— 启用(hive-site.xml 中):
— hive.security.authorization.enabled=true
— hive.security.authorization.manager=org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory
— 创建角色
CREATE ROLE analyst;
CREATE ROLE data_engineer;
— 授予角色权限
GRANT SELECT ON DATABASE sales_db TO ROLE analyst;
GRANT ALL ON TABLE employees TO ROLE data_engineer;
GRANT SELECT ON TABLE employees (name, dept) TO ROLE analyst; — 列级权限
— 将角色赋予用户
GRANT ROLE analyst TO USER alice;
GRANT ROLE data_engineer TO USER bob;
— 撤销权限
REVOKE SELECT ON DATABASE sales_db FROM ROLE analyst;
REVOKE ROLE analyst FROM USER alice;
— 查看权限
SHOW GRANT USER alice ON TABLE employees;
SHOW ROLE GRANT USER alice;
SHOW GRANTS ON TABLE employees;
— 删除角色
DROP ROLE analyst;
17.3 与 Apache Ranger 集成
Apache Ranger 提供企业级细粒度权限控制:
用户请求 → HiveServer2 → Ranger 插件鉴权 → 允许/拒绝
↑
Ranger Admin(策略管理中心)
↑
Ranger Audit(审计日志)
Ranger 支持:
- 数据库/表/列/行级别权限控制
- 基于用户/组/角色的权限策略
- 数据掩码(敏感数据自动脱敏)
- 行过滤(不同用户看到不同行)
- 完整的审计日志
18. Hive 与生态系统集成
18.1 Hive on Spark
# 在 hive-site.xml 中配置
# hive.execution.engine=spark
# spark.master=yarn
# spark.submit.deployMode=cluster
— 切换到 Spark 引擎
SET hive.execution.engine=spark;
— Spark 相关配置
SET spark.executor.memory=4g;
SET spark.executor.cores=2;
SET spark.executor.instances=10;
SET spark.dynamicAllocation.enabled=true;
— 执行查询(透明使用 Spark 计算)
SELECT dept, AVG(salary) FROM employees GROUP BY dept;
18.2 与 Spark SQL 共享 Metastore
Spark SQL 和 Hive 可以共享同一个 Metastore,让两个系统看到相同的表结构:
// Spark 代码中配置 Hive Metastore
val spark = SparkSession.builder()
.appName("HiveIntegration")
.config("spark.sql.warehouse.dir", "/user/hive/warehouse")
.config("hive.metastore.uris", "thrift://localhost:9083")
.enableHiveSupport()
.getOrCreate()
// 直接查询 Hive 表
spark.sql("SELECT * FROM sales_db.orders LIMIT 10").show()
// Spark 写入的表在 Hive 中可见
spark.sql("""
CREATE TABLE IF NOT EXISTS spark_result
USING ORC
AS SELECT dept, SUM(salary) FROM employees GROUP BY dept
""")
18.3 与 HBase 集成
— 创建 Hive-HBase 映射表(通过 HBase StorageHandler)
CREATE TABLE hbase_users (
key STRING,
name STRING,
age INT,
email STRING
)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES (
'hbase.columns.mapping' = ':key,info:name,info:age,info:email'
)
TBLPROPERTIES ('hbase.table.name' = 'users');
— 通过 Hive 查询 HBase 数据
SELECT * FROM hbase_users WHERE key = 'user001';
18.4 与 Apache Iceberg 集成(Hive 4.x)
Apache Iceberg 是新一代开放表格式,Hive 4.x 对其提供原生支持:
— 创建 Iceberg 表
CREATE TABLE iceberg_orders (
order_id BIGINT,
user_id INT,
amount DECIMAL(10,2),
status STRING,
create_ts TIMESTAMP
)
STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'
LOCATION '/warehouse/iceberg/orders'
TBLPROPERTIES (
'table_type'='ICEBERG',
'format-version'='2', — Iceberg v2(支持 Row-level Updates)
'write.delete.mode'='merge-on-read' — 删除模式
);
— Iceberg 支持的时间旅行(Time Travel)
— 查询历史快照
SELECT * FROM iceberg_orders FOR SYSTEM_TIME AS OF '2024-01-01 00:00:00';
SELECT * FROM iceberg_orders FOR SYSTEM_VERSION AS OF 12345678;
— 查看表历史
SELECT * FROM iceberg_orders.history;
SELECT * FROM iceberg_orders.snapshots;
— Iceberg Z-order 排序(Hive 4.x 新特性)
ALTER TABLE iceberg_orders EXECUTE OPTIMIZE(ZORDER BY (user_id, create_ts));
18.5 与 Sqoop 集成
# Sqoop 从 MySQL 导入数据到 Hive 表
sqoop import \\
–connect jdbc:mysql://mysql-host:3306/sales \\
–username root –password secret \\
–table orders \\
–hive-import \\
–hive-database sales_db \\
–hive-table orders_from_mysql \\
–hive-overwrite \\
–num-mappers 4
# Sqoop 将 Hive 表数据导出到 MySQL
sqoop export \\
–connect jdbc:mysql://mysql-host:3306/sales \\
–username root –password secret \\
–table mysql_target \\
–hcatalog-database sales_db \\
–hcatalog-table hive_source
19. Hive 4.x 新特性
19.1 Iceberg v3 深度集成
— 支持 Iceberg v3 功能:Deletion Vectors(删除向量)
— 比 MoR 模式更高效的行级删除实现
CREATE TABLE orders_v3 (...)
STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'
TBLPROPERTIES (
'format-version'='3',
'write.delete.mode'='merge-on-read'
);
— Z-ordering 优化(空间近邻填充曲线,提升多列过滤性能)
ALTER TABLE orders_v3 EXECUTE OPTIMIZE(ZORDER BY (user_id, date));
— Variant 类型(半结构化数据,类似 JSON Schema)
CREATE TABLE semi_struct (id BIGINT, data VARIANT);
19.2 JDK 21 支持
Hive 4.x 支持 Java 21,可使用虚拟线程(Virtual Threads)提升 HS2 并发性能。
19.3 HMS REST Catalog
— Hive Metastore 暴露 REST API,兼容 Apache Iceberg REST Catalog 协议
— 允许 Spark、Flink 通过标准 REST API 访问 Hive 元数据
19.4 内置自动 Compaction
Hive 4.x 加入了 ACID 表的自动 Compaction 功能,无需手动触发:
— 查看 compaction 队列
SHOW COMPACTIONS;
— 手动触发 compaction(Major:合并所有增量到基础文件)
ALTER TABLE student COMPACT 'major';
— 手动触发 Minor compaction(合并增量文件)
ALTER TABLE student COMPACT 'minor';
20. 常见问题与排查
20.1 Hive 查询卡住不动
排查步骤:
# 1. 查看 YARN 作业状态
yarn application -list
yarn application -status <application_id>
# 2. 查看 Hive 日志
tail -f $HIVE_HOME/logs/hive.log
# 3. 查看 YARN 作业日志
yarn logs -applicationId application_XXXXX
# 4. 检查是否有 Reducer 数据倾斜(YARN UI http://master:8088 中查看各 Reducer 进度)
20.2 “Too many dynamic partitions” 错误
— 错误信息:Number of dynamic partitions created is 2000, which is more than 1000
— 解决:增大动态分区限制
SET hive.exec.max.dynamic.partitions=5000;
SET hive.exec.max.dynamic.partitions.pernode=1000;
20.3 Out of Memory 错误
— 增大 Map/Reduce 内存
SET mapreduce.map.memory.mb=4096;
SET mapreduce.reduce.memory.mb=8192;
SET mapreduce.map.java.opts=–Xmx3276m;
SET mapreduce.reduce.java.opts=–Xmx6553m;
— 增大 Tez 容器大小
SET tez.task.resource.memory.mb=4096;
SET tez.task.launch.cmd–opts=–Xmx3276m;
20.4 Metastore 连接失败
# 检查 Metastore 服务是否运行
netstat -tuln | grep 9083
# 或
ps aux | grep HiveMetaStore
# 重启 Metastore
pkill -f HiveMetaStore
nohup hive –service metastore > /tmp/metastore.log 2>&1 &
# 检查 MySQL 连接
mysql -h localhost -u hive -p metastore
# 检查 schema 版本
schematool -dbType mysql -info
20.5 “Unable to move source” 错误
# 原因:HDFS 临时目录权限问题
hdfs dfs -chmod 777 /tmp/hive
hdfs dfs -chown -R hive:hdfs /user/hive/warehouse
# 在 hive-site.xml 中设置 hive 临时目录
# hive.exec.scratchdir=/tmp/hive
# hive.downloaded.resources.dir=/tmp/hive/resources
20.6 全表扫描警告
— 错误:Strict mode requires that a partition filter is present before returning from this call
— 原因:hive.mapred.mode=strict 时,查询分区表必须有分区条件
— 解决方案1:添加分区条件
SELECT * FROM user_events WHERE dt = '2024-01-01';
— 解决方案2:临时关闭 strict 模式
SET hive.mapred.mode=nonstrict;
20.7 Join 内存溢出(小表 MapJoin 失败)
— 增大 MapJoin 阈值
SET hive.mapjoin.smalltable.filesize=128000000; — 128MB
SET hive.auto.convert.join.noconditionaltask.size=128000000;
— 或关闭自动 MapJoin,改用普通 Join
SET hive.auto.convert.join=false;
21. 最佳实践总结
21.1 建表规范
— ✅ 推荐建表模式
CREATE TABLE sales_order (
order_id BIGINT COMMENT '订单ID(主键)',
user_id INT COMMENT '用户ID',
product_id INT COMMENT '商品ID',
amount DECIMAL(12,2) COMMENT '订单金额',
create_ts TIMESTAMP COMMENT '下单时间'
)
COMMENT '销售订单明细表'
PARTITIONED BY (dt STRING COMMENT '日期分区 yyyyMMdd')
STORED AS ORC
TBLPROPERTIES (
'orc.compress'='SNAPPY',
'author'='data_eng_team',
'create_time'='2024-01-01'
);
21.2 数据导入规范
# 1. 批量数据:使用 LOAD DATA 或 INSERT OVERWRITE
# 2. 增量数据:INSERT INTO(追加)
# 3. 大批量 ETL:INSERT OVERWRITE TABLE … SELECT …(效率最高)
# 4. 导入后运行 ANALYZE TABLE 收集统计信息
21.3 查询优化清单
□ 分区表查询必须包含分区条件
□ 优先使用 ORC 或 Parquet 格式
□ 小表 JOIN 使用 MAPJOIN hint
□ 避免 SELECT *,只查需要的列
□ GROUP BY 使用高基数列(低基数考虑分桶后 SMB Join)
□ 使用 EXPLAIN 分析执行计划
□ 对核心表执行 ANALYZE TABLE 收集统计信息
□ 避免在 WHERE 条件中对分区列使用函数
□ 大查询优先使用 Tez 引擎
□ 数据倾斜时使用 hive.groupby.skewindata=true
21.4 EXPLAIN 使用
— 查看执行计划
EXPLAIN SELECT dept, COUNT(*) FROM employees WHERE salary > 10000 GROUP BY dept;
— 查看详细执行计划(含操作符树)
EXPLAIN EXTENDED SELECT ...;
— 查看依赖关系
EXPLAIN DEPENDENCY SELECT ...;
— 查看向量化信息
EXPLAIN VECTORIZATION SELECT ...;
— 查看 CBO 相关信息(需 SET hive.cbo.enable=true)
EXPLAIN ANALYZE SELECT ...;
21.5 Hive 命令行技巧
# 执行单个 HQL 后退出
hive -e "SELECT COUNT(*) FROM employees"
# 执行 HQL 脚本文件
hive -f /data/scripts/report.hql
# 传递变量到 HQL 脚本(使用 hiveconf)
hive -f report.hql –hiveconf dt=2024-01-01
# 在 HQL 中使用:WHERE dt = '${hiveconf:dt}'
# 静默模式(去掉 INFO 日志)
hive -S -e "SELECT …"
# 初始化 HQL(每次启动时执行)
hive –hiveconf hive.session.id=mysession -i /data/scripts/init.hql -f report.hql
22. Hive 与其他技术对比
22.1 Hive vs Spark SQL
| 擅长场景 | 超大批量 ETL,PB 级离线处理 | 复杂分析,迭代计算,ML 管道 |
| 查询延迟 | 秒~分钟级 | 亚秒~秒级 |
| 内存使用 | 磁盘为主,内存需求低 | 内存密集型 |
| SQL 兼容 | HiveQL(HQL),自己的方言 | ANSI SQL,兼容 HiveQL |
| 生态整合 | Hadoop 原生,Metastore 标准 | 支持 Hive Metastore |
| 小文件处理 | 需要手动合并 | 自动处理能力强 |
| 流批一体 | 仅批处理 | 批处理 + Structured Streaming |
22.2 Hive vs Presto/Trino
| 定位 | 批处理 ETL 工具 | 交互式 OLAP 查询引擎 |
| 延迟 | 高(秒~分钟) | 低(毫秒~秒,MPP 并行) |
| 数据源 | HDFS/S3/HBase | 多源联邦:Hive/MySQL/S3/Kafka 等 |
| 大数据集 | 擅长(PB 级 ETL) | 内存有限,超大结果集可能 OOM |
| SQL 支持 | HiveQL 扩展 | 接近标准 ANSI SQL |
| 使用场景 | 数据入库、转换、批量报表 | BI 即席查询、实时大屏 |
22.3 Hive vs Impala
| 架构 | MapReduce/Tez/Spark 执行 | 原生 MPP,C++ 实现 |
| 延迟 | 高 | 低(内存 MPP,毫秒级) |
| 容错 | 强(MR/Tez 容错机制) | 弱(查询失败需重试) |
| UDF | Java/Python | Java(有限) |
| 共享 Metastore | 是(HMS) | 是(共享 Hive HMS) |
| 适用场景 | 大批量 ETL | 快速分析查询 |
22.4 2024 年 Hive 的定位
Hive 在现代数据栈中的核心价值仍然存在:
数据湖架构中的 Hive 角色(2024):
存储层: HDFS / S3 / OSS(对象存储)
表格式: Hive 表 / Apache Iceberg / Apache Hudi / Apache Delta Lake
批处理: Hive(ETL)/ Spark(复杂计算)
即席查询:Presto / Trino / Spark SQL
元数据: Hive Metastore(HMS,事实上的行业标准)
HMS(Hive Metastore Service)已成为大数据生态的元数据中枢,即使不使用 Hive 做查询,Spark、Presto、Flink 等都依赖 HMS 管理表元数据。这是 Hive 在现代架构中最核心的价值所在。
23. 附录:配置项速查 & 官方资源
23.1 重要配置项汇总
| hive.execution.engine | mr | 执行引擎:mr/tez/spark |
| hive.metastore.warehouse.dir | /user/hive/warehouse | Hive 仓库目录 |
| hive.exec.dynamic.partition | false | 是否启用动态分区 |
| hive.exec.dynamic.partition.mode | strict | 动态分区模式:strict/nonstrict |
| hive.exec.max.dynamic.partitions | 1000 | 最大动态分区数 |
| hive.auto.convert.join | true | 自动转换 MapJoin |
| hive.mapjoin.smalltable.filesize | 25MB | MapJoin 小表阈值 |
| hive.cbo.enable | true | 启用 CBO 优化器 |
| hive.vectorized.execution.enabled | true | 启用向量化执行 |
| hive.exec.parallel | false | 并行执行多个 Stage |
| hive.merge.mapfiles | true | 合并 Map-only 输出小文件 |
| hive.merge.mapredfiles | false | 合并 MR 输出小文件 |
| hive.groupby.skewindata | false | 数据倾斜时随机分发 |
| hive.map.aggr | true | Map 端预聚合 |
| hive.mapred.mode | nonstrict | strict 模式强制分区条件 |
| hive.optimize.skewjoin | false | 倾斜 Join 优化 |
| hive.server2.thrift.port | 10000 | HiveServer2 端口 |
| hive.metastore.port | 9083 | Metastore Thrift 端口 |
| hive.server2.webui.port | 10002 | HiveServer2 Web UI 端口 |
23.2 默认端口速查
| Hive Metastore | 9083 | Thrift |
| HiveServer2(JDBC/ODBC) | 10000 | Thrift/HTTP |
| HiveServer2 Web UI | 10002 | HTTP |
| Hive CLI(本地) | – | 本地进程 |
23.3 官方资源链接
| Apache Hive 官网 | https://hive.apache.org/ |
| 官方 Wiki 文档 | https://cwiki.apache.org/confluence/display/Hive/Home |
| Hive 下载页面 | https://hive.apache.org/downloads.html |
| 快速开始指南 | https://hive.apache.org/development/quickstart/ |
| 语言手册(DDL) | https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL |
| 语言手册(DML) | https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DML |
| 语言手册(UDF) | https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF |
| 设计文档 | https://hive.apache.org/development/desingdocs/design/ |
| 管理员手册 | https://hive.apache.org/docs/latest/admin/ |
| HiveServer2 文档 | https://cwiki.apache.org/confluence/display/Hive/Setting+Up+HiveServer2 |
| Hive GitHub | https://github.com/apache/hive |
23.4 常用 SQL 速查
— 查看当前配置
SET hive.execution.engine; — 查看单个配置
SET; — 查看所有配置
— 查看当前数据库
SELECT current_database();
— 查看 Hive 版本
SELECT version();
— 查看函数列表
SHOW FUNCTIONS;
SHOW FUNCTIONS LIKE 'str*';
— 查看建表语句
SHOW CREATE TABLE table_name;
— 查看分区列表
SHOW PARTITIONS table_name;
— 查看锁
SHOW LOCKS table_name;
— 释放锁
UNLOCK TABLE table_name;
— 查看正在运行的查询(HS2 Web UI)
— http://localhost:10002/queries
— 执行计划
EXPLAIN [EXTENDED|VECTORIZATION|DEPENDENCY|AUTHORIZATION|ANALYZE] query;



