一、分区的核心概念
Hive 的分区 本质是按指定字段将数据文件划分到不同的 HDFS 目录 (比如按日期dt=20260106、按地区region=cn),核心目的是:
- 避免全表扫描,只扫描指定分区的数据,大幅提升查询效率;
- 方便数据按业务维度(时间 / 地区 / 部门)管理。
关键特点:
- 分区字段是伪列(不在数据文件的真实列中),仅用于划分目录;
- 分区表创建时需用
PARTITIONED BY (分区字段 数据类型)声明。
二、静态分区(Static Partition)
1. 核心定义
静态分区指插入 / 加载数据时,分区字段的值是手动指定的固定值 (比如明确指定dt='20260106'),适用于分区值已知且固定的场景。
2. 操作示例
步骤 1:创建分区表
以 "学生成绩表" 为例,按班级(class)分区:
sql
-- 创建分区表(管理表)
CREATE TABLE score (
id INT, -- 学生ID(真实列)
name STRING, -- 学生姓名(真实列)
score INT -- 成绩(真实列)
)
PARTITIONED BY (class STRING) -- 分区字段:班级(伪列)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' -- 数据分隔符为制表符
STORED AS TEXTFILE; -- 文件格式
步骤 2:加载数据到静态分区
有两种常见方式:LOAD DATA(加载文件)和INSERT...SELECT(插入查询结果)。
方式 1:LOAD DATA 加载本地文件到静态分区
假设本地有文件/root/score_2201.txt,内容为:
plaintext
1 张三 90
2 李四 85
3 王五 92
执行以下 SQL,将数据加载到class=2201分区:
sql
LOAD DATA LOCAL INPATH '/root/score_2201.txt'
INTO TABLE score
PARTITION (class='2201'); -- 手动指定分区值(静态)
方式 2:INSERT...SELECT 插入数据到静态分区
假设已有表score_all,包含所有班级数据,现在将 2202 班数据插入到静态分区:
sql
INSERT OVERWRITE TABLE score
PARTITION (class='2202') -- 手动指定分区值(静态)
SELECT id, name, score FROM score_all WHERE class='2202';
步骤 3:查询静态分区数据
sql
-- 只扫描2201分区,效率高
SELECT * FROM score WHERE class='2201';
三、动态分区(Dynamic Partition)
1. 核心定义
动态分区指插入数据时,分区字段的值由查询结果自动推导(无需手动指定),适用于分区值未知、需批量处理多个分区的场景(比如按日期批量导入近 30 天数据)。
2. 前置配置(必须)
动态分区默认关闭,需先设置以下参数:
sql
-- 开启动态分区(默认false)
SET hive.exec.dynamic.partition=true;
-- 设置为非严格模式(默认strict,要求至少一个静态分区,nonstrict允许全动态)
SET hive.exec.dynamic.partition.mode=nonstrict;
-- 可选:设置每个节点允许的最大动态分区数(防止分区过多)
SET hive.exec.max.dynamic.partitions.pernode=1000;
3. 操作示例
延续上面的score表,现在需要将score_all中的所有班级数据自动按班级分区插入(无需手动指定每个班级)。
步骤 1:准备源表数据
假设score_all表内容:
| id | name | score | class |
|---|---|---|---|
| 1 | 张三 | 90 | 2201 |
| 2 | 李四 | 85 | 2201 |
| 3 | 王五 | 92 | 2202 |
| 4 | 赵六 | 88 | 2202 |
| 5 | 钱七 | 95 | 2203 |
步骤 2:插入数据到动态分区
sql
-- 动态分区:分区字段class的值由SELECT结果的最后一列自动推导
INSERT OVERWRITE TABLE score
PARTITION (class) -- 仅声明分区字段,不指定值(动态)
SELECT id, name, score, class FROM score_all; -- 最后一列必须是分区字段class
关键说明:
PARTITION (class)仅声明分区字段,不写值;SELECT语句的最后一列必须是分区字段 (这里是class),Hive 会根据该列的值自动创建对应分区(2201/2202/2203)。
步骤 3:验证动态分区结果
sql
-- 查看所有分区
SHOW PARTITIONS score;
-- 输出:
-- class=2201
-- class=2202
-- class=2203
-- 查询2203分区数据
SELECT * FROM score WHERE class='2203';
-- 输出:
-- 5 钱七 95 2203
四、静态分区 vs 动态分区 对比
| 维度 | 静态分区 | 动态分区 |
|---|---|---|
| 分区值指定 | 手动固定值 | 由查询结果自动推导 |
| 适用场景 | 单个 / 少量已知分区 | 批量 / 未知分区(如按日期批量) |
| 配置要求 | 无需额外配置 | 需开启动态分区参数 |
| 语法特点 | PARTITION (class='2201') | PARTITION (class) |
总结
- 分区的核心价值:将数据按业务维度(如班级 / 日期)拆分到不同目录,避免全表扫描,提升查询效率;
- 静态分区:分区值手动指定,适合少量、已知分区的场景,无需额外配置;
- 动态分区 :分区值自动推导,适合批量、未知分区的场景,需先开启
nonstrict模式,且 SELECT 最后一列必须是分区字段。