本文系统介绍了Hive的核心技术与优化策略。
主要内容包括:
1)分区与分桶技术,详细讲解静态/动态分区实现方法和分桶原理;
2)数据倾斜问题及解决方案,涵盖JOIN、GROUPBY等场景的优化方法;
3)Hive高级功能,如存储格式选择、排序方式比较和自定义函数开发;
4)性能优化体系,从运维配置、模型设计到SQL编写的多维度优化建议;
5)典型面试问题解析,如大表关联处理方案和参数调优技巧。
文章通过大量实例演示和命令速查表,帮助读者掌握Hive的核心技术要点和实战优化方法。
(课堂笔记)Hive 分区、分桶与数据倾斜
一、Hive 分区
1.1 什么是分区?
分区是将表的数据按照某个字段的值,分成不同的目录存储。查询时可以只扫描特定分区,大大提高查询效率。
1.2 静态分区
定义:使用分区时必须指定分区名(key=value),这就是静态分区。
示例场景
三位任课老师的成绩文件:
| 科目 | 文件名 | 内容 |
|---|---|---|
| 语文 | chinese | 101,zhangsan,100 102,lisi,88 103,wangwu,78 |
| 数学 | math | 101,zhangsan,89 102,lisi,56 103,wangwu,60 |
| 英语 | english | 101,zhangsan,77 102,lisi,67 103,wangwu,98 |
操作步骤
步骤1:构造数据文件
bash
cd /home/hadoop/2608/test
touch chinese math english
# 依次编辑文件,写入内容
步骤2:创建分区表
sql
create table t_class(
sno int,
sname string,
score int
)
partitioned by (subject string)
row format delimited fields terminated by ',';
步骤3:加载数据到指定分区
sql
-- 加载语文数据到 yuwen 分区
load data local inpath '/home/hadoop/2608/test/chinese'
into table t_class partition (subject='yuwen');
-- 加载数学数据到 shuxue 分区
load data local inpath '/home/hadoop/2608/test/math'
into table t_class partition (subject='shuxue');
-- 加载英语数据到 yingyu 分区
load data local inpath '/home/hadoop/2608/test/english'
into table t_class partition (subject='yingyu');
步骤4:查询某个分区数据
sql
select * from t_class where subject = 'yuwen';
步骤5:新增分区
sql
alter table t_class add partition (subject='history');
步骤6:插入数据到分区
sql
load data ... -- 方式一:加载文件
-- 方式二:从其他表插入
insert overwrite table t_class partition (subject='history')
select sno, sname, score
from t_class
where subject = 'yuwen';
步骤7:删除分区
| 方式 | 命令 |
|---|---|
| 页面删除 | 直接在 Web 界面操作 |
| HDFS 删除 | hadoop fs -rm -r 分区目录 |
| Hive 删除 | alter table t_class drop partition (subject='math'); |
1.3 静态分区练习
练习要求
构造三个月份的产品销售数据:
| 文件 | 内容 |
|---|---|
| 202001 | 111,apple,7788 112,huawei,8899 113,xiaomi,6666 |
| 202002 | 111,apple,656 112,huawei,77567 113,xiaomi,86786 |
| 202003 | 111,apple,546 112,huawei,768678 113,xiaomi,867876 |
练习答案
1. 创建分区表
sql
create table t_sales(
pro_id int,
pro_name string,
quantity int
)
partitioned by (month int)
row format delimited fields terminated by ',';
2. 加载数据到指定分区
sql
load data local inpath '/home/hadoop/2608/test/202001'
into table t_sales partition (month=202001);
load data local inpath '/home/hadoop/2608/test/202002'
into table t_sales partition (month=202002);
load data local inpath '/home/hadoop/2608/test/202003'
into table t_sales partition (month=202003);
3. 添加分区
sql
alter table t_sales add partition (month=202004);
4. 从现有分区插入数据到新分区
sql
insert overwrite table t_sales partition (month=202004)
select
pro_id,
pro_name,
quantity + 1000
from t_sales
where month = 202002;
5. 删除分区
sql
alter table t_sales drop partition (month=202001);
1.4 动态分区
定义:分区名未知时,MR 自动读取数据,读取分区列,将数据写入对应的分区。
核心特点
| 特点 | 说明 |
|---|---|
| 自动分区 | MR 自动根据分区列的值创建分区 |
| 使用简单 | 可以把分区表当作普通表使用 |
| 位置要求 | 分区列必须在 SELECT 字段的最后面 |
示例:将 EMP 表数据写入分区表(按 deptno 分区)
步骤1:创建分区表
sql
create table fenqu_emp(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal int,
comm int
)
partitioned by (deptno int)
row format delimited fields terminated by '\t';
步骤2:加载数据
sql
-- 方式一:直接加载文件
load data local inpath '/home/hadoop/2608/test/emp'
into table fenqu_emp;
-- 方式二:动态分区插入(需要结果集提供分区值)
insert into fenqu_emp
select * from fenqu_emp
where deptno is not null;
注意:动态分区时,SELECT 的最后一个字段必须匹配分区列(deptno)
1.5 动态分区练习
练习要求
将 dept 表的数据,以 deptno 分区的方式存入 fenqu_dept。
目标结果:HDFS 的 fenqu_dept 目录下有 4 个子目录:
-
deptno=10
-
deptno=20
-
deptno=30
-
deptno=40
练习答案
sql
-- 1. 创建分区表
create table fenqu_dept(
dname string,
loc string
)
partitioned by (deptno int)
row format delimited fields terminated by '\t';
-- 2. 动态分区插入
insert into fenqu_dept
select dname, loc, deptno from dept;
二、Hive 分桶
2.1 什么是分桶?
当分区数据分布不均匀时,可以使用分桶将数据按照哈希值均匀分配到多个桶(文件)中。
2.2 分桶原理
text
每条数据写入时:MOD(哈希值, 桶数) → 决定放入哪个桶
| 桶数 | 每个桶数据量 |
|---|---|
| 5 个桶 | 1 亿条数据 → 每个桶约 2000 万条 |
2.3 分表示例:按 ENAME 分桶
步骤1:创建分桶表
sql
create table fentong_emp(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal int,
comm int,
deptno int
)
clustered by (ename) into 3 buckets
row format delimited fields terminated by '\t';
步骤2:写入数据
sql
-- 分桶表就是普通表,直接插入
insert into fentong_emp
select * from emp;
-- ❌ 不推荐用 load data,因为不会触发分桶
-- load data local inpath '/home/hadoop/2608/test/emp' into table fentong_emp;
2.4 分桶练习
练习要求
创建分桶表 fentong_dept,分桶键为 DNAME,分 2 个桶,并将 dept 表数据写入。
练习答案
sql
-- 1. 创建分桶表
create table fentong_dept(
deptno int,
dname string,
loc string
)
clustered by (dname) into 2 buckets
row format delimited fields terminated by '\t';
-- 2. 写入数据
insert into fentong_dept
select * from dept;
2.5 分区 vs 分桶对比
| 对比项 | 分区 | 分桶 |
|---|---|---|
| 存储方式 | 分目录存放 | 分文件存放 |
| 分配规则 | 有规律(相同分区值放一起) | 无规律(哈希取模) |
| 字段要求 | 分区字段在数据文件中不存在 | 分桶字段在数据文件中真实存在 |
| 用途 | 提高查询效率 | 便于数据采样 |
2.6 分桶的好处
-
便于后期的数据采样
-
使数据分布更均匀
2.7 桶的个数定义规则
text
桶数 = (总文件大小 / 128M) × 2
说明:128M 是 HDFS 的 Block Size 默认存储大小
三、数据倾斜
3.1 什么是数据倾斜?
Hive 将 SQL 转换成 MR 程序运行时,Map 阶段生成的键值对分布不均,导致某些节点处理的数据量非常大,某些节点非常少。
3.2 数据倾斜示例
sql
SELECT 省份, SUM(金额)
FROM 订单表
GROUP BY 省份;
| 省份 | 数据量 | 问题 |
|---|---|---|
| 广东 | 10 亿条 | ⚠️ 数据量大 |
| 浙江 | 2 亿条 | 正常 |
| 云南 | 1000 万条 | 正常 |
| 内蒙 | 1 万条 | 正常 |
总结:Map 阶段数据分布不均,导致单节点负载过高。
3.3 数据倾斜的解决方案
方案1:JOIN 导致的数据倾斜
问题场景:
sql
select *
from 订单表 m
left join 用户表 n on m.客户ID = n.客户ID
解决方案:
| 方法 | 说明 |
|---|---|
| Key 值打散 | case when m.客户ID is null then rand() else m.客户ID end = n.客户ID |
| Map Join | 把小表放到内存中,驱动大表,避免 shuffle 运算 |
sql
-- Map Join 写法
select /*+ mapjoin(n) */ *
from 订单表 m
left join 用户表 n on m.客户ID = n.客户ID
方案2:GROUP BY 导致的数据倾斜
解决方案:
| 方法 | 说明 |
|---|---|
| 缩小粒度 | GROUP BY 省份 → GROUP BY 城市 |
| 参数调优 | set hive.groupby.xxx = True set hive.map.xxx = True |
方案3:小文件过多
问题:一个目录有几万甚至几十万个小文件
解决方案:
| 方法 | 说明 |
|---|---|
| 合并小文件 | 设置 combine 参数为 True |
| Insert Overwrite | 用 insert overwrite 方式合并小文件 |
方案4:数据类型不一致
问题场景:
sql
select *
from aaa
left join bbb on aaa.id = bbb.id;
-- aaa.id 是 int (101)
-- bbb.id 是 string ('101')
解决方案:
sql
-- 用 CAST 统一数据类型
select *
from aaa
left join bbb on cast(aaa.id as string) = bbb.id;
3.4 面试题示例
Q:数据倾斜有碰到过吗?原因是什么?怎么解决的?
A: 之前有碰到过几次,主要原因是因为 key 值分布不均导致的。
具体案例1:大表 JOIN 小表
-
某些科目数据在大表里面体量非常大,有的比较少
-
导致 JOIN 时 Map 阶段分布不均
-
解决方法:使用 Map Join,把小表放到内存驱动大表,避免数据倾斜
具体案例2:小文件过多
-
开发监控脚本,监控 HDFS 上的分区目录文件个数
-
某个分区表子目录文件个数超过阈值(5000),有几万个文件
-
导致跑批任务时间非常久
-
解决方法 :通过
insert overwrite方式合并小文件,解决数据倾斜
四、命令速查表
| 操作 | 命令 |
|---|---|
| 创建分区表 | create table ... partitioned by (col type) |
| 静态分区加载 | load data ... into table ... partition (col='value') |
| 添加分区 | alter table ... add partition (col='value') |
| 删除分区 | alter table ... drop partition (col='value') |
| 创建分桶表 | create table ... clustered by (col) into n buckets |
| 插入分桶表 | insert into ... select ...(不能用 load data) |
| Map Join | select /*+ mapjoin(小表) */ ... |
五、关键概念总结
| 概念 | 核心要点 |
|---|---|
| 静态分区 | 指定分区名,手动加载 |
| 动态分区 | 自动识别分区,分区列在 SELECT 最后 |
| 分桶 | 哈希取模均匀分布,便于采样 |
| 数据倾斜 | key 分布不均导致,可用 Map Join、打散 key、合并小文件解决 |
补充:Hive 周边 & 面试常问问题
本笔记针对初学者,将课堂笔记中笼统的概念和理论进行详细解释,帮助理解。
一、Linux 环境执行 Hive 脚本
1.1 为什么需要在 Linux 中执行 Hive 脚本?
在实际工作中,我们通常不会手动在 Hive 窗口一条条输入 SQL,而是:
-
将写好的 SQL 保存成文件
-
通过 Linux 命令批量执行
-
配合调度工具(如 Azkaban)定时运行
1.2 方式一:hive -e
bash
hive -e "SQL语句"
作用:切换到 Hive 窗口执行 SQL,执行完后自动退出 Hive 窗口,返回到 Linux 命令行。
示例1:直接执行查询
bash
hive -e "select * from a2608.fenqu_emp"
注意 :如果之前没有用 use 数据库名; 切换数据库,则表名需要带上数据库名,格式为 数据库名.表名。
示例2:多条 SQL 用分号隔开
bash
hive -e "use mydb; show tables; select * from emp limit 10;"
1.3 方式二:hive -f
bash
hive -f SQL文件路径
作用:将文件内容当作 Hive 命令执行,执行完后自动退出。
示例:
bash
# 1. 创建一个 SQL 文件
echo "select * from a2608.fenqu_emp;" > aaa.sql
# 2. 执行这个文件
hive -f aaa.sql
1.4 两种方式对比
| 方式 | 适用场景 | 优点 |
|---|---|---|
hive -e |
SQL 较短,一次性执行 | 简单快捷 |
hive -f |
SQL 较长,需要保存记录 | 便于复用和版本管理 |
二、Hive 的文件存储格式
2.1 什么是存储格式?
存储格式决定了数据在 HDFS 上以什么方式组织和存放。
2.2 常见存储格式
| 格式 | 类型 | 特点 |
|---|---|---|
| TEXTFILE | 行式存储(默认) | 纯文本,可读性好,占用空间大 |
| ORC | 列式存储 | 压缩比高,查询快,占用空间小 |
| SEQUENCEFILE | 行式存储 | 二进制格式,支持压缩 |
2.3 行式存储 vs 列式存储
行式存储(如 TEXTFILE):
text
数据按行存放:101,张三,90 → 102,李四,85 → 103,王五,88
查询时即使只需要"姓名"列,也会读取整行数据
列式存储(如 ORC):
text
数据按列存放:101,102,103 → 张三,李四,王五 → 90,85,88
查询时只需要读取需要的列,大大减少 IO
2.4 如何选择存储格式?
| 场景 | 推荐格式 | 原因 |
|---|---|---|
| 数据量大(TB/PB 级) | ORC | 压缩比高(节省存储),查询快(列式存储) |
| 数据量小(几百 MB) | TEXTFILE | 简单直观,便于排查问题 |
| 需要与其他工具交互 | TEXTFILE | 通用性最好 |
2.5 建表时指定存储格式
sql
-- 不指定时,默认是 TEXTFILE
create table aaa(id int)
row format delimited fields terminated by ','
stored as orc; -- 指定 ORC 格式
-- 其他格式示例
stored as textfile; -- 文本格式(默认)
stored as sequencefile; -- 序列文件格式
三、Hive 的特殊功能
3.1 存储过程
| 问题 | 答案 |
|---|---|
| Hive 有存储过程吗? | 没有 |
| 为什么没有? | Hive 定位是数据仓库工具,不是传统数据库,不支持过程式编程 |
3.2 自定义函数(UDF)
什么是 UDF?
当 Hive 自带的函数无法满足业务需求时,可以自己编写 Java 代码实现自定义函数。
开发步骤:
-
编写 Java 类,继承
UDF类 -
实现
evaluate方法 -
打包成 JAR 包
-
在 Hive 中注册并使用
sql
-- 注册自定义函数
add jar /path/to/myudf.jar;
create temporary function my_func as 'com.example.MyUDF';
-- 使用自定义函数
select my_func(column) from table;
3.3 索引
| 问题 | 答案 |
|---|---|
| Hive 有索引吗? | 通常没有(3.0 版本后有,但不常用) |
| 为什么不用索引? | 分区和分桶已经提供了类似索引的查询优化效果 |
四、Hive 的四种排序
4.1 排序方式对比
| 排序方式 | 英文 | 说明 | 适用场景 |
|---|---|---|---|
| 全局排序 | ORDER BY | 对所有数据排序,只有一个 reducer | 数据量小时使用 |
| 分区排序 | SORT BY | 每个 reducer 内部排序,不保证全局有序 | 数据量大,只关心局部有序 |
| 分发排序 | DISTRIBUTE BY | 按指定字段分发到不同 reducer | 需要将相同 key 的数据发到同一 reducer |
| 分区+排序 | CLUSTER BY | = DISTRIBUTE BY + SORT BY(相同字段) | 同时完成分发和排序 |
4.2 详细解释
ORDER BY(全局排序)
sql
select * from emp order by sal desc;
-
特点 :所有数据进入一个 reducer,保证全局有序
-
缺点:数据量大时非常慢
-
注意 :需要设置
set hive.mapred.mode=nonstrict;(关闭严格模式)
SORT BY(分区排序)
sql
select * from emp sort by sal desc;
-
特点 :每个 reducer 内部 排序,但 reducer 之间无序
-
举例:如果有 3 个 reducer,每个 reducer 输出的数据是排序的,但 reducer1 的最后一个值可能大于 reducer2 的第一个值
DISTRIBUTE BY(分发)
sql
select * from emp distribute by deptno;
-
特点 :将相同 deptno 的数据分发到同一个 reducer
-
用途:为后续的排序或聚合做准备
CLUSTER BY(分区+排序)
sql
select * from emp cluster by deptno;
-
等价于 :
distribute by deptno sort by deptno -
特点:按相同字段分发和排序
4.3 图解排序方式
text
ORDER BY: [所有数据] → reducer1 → [全局有序结果]
SORT BY: [数据] → reducer1 → [有序子集1]
[数据] → reducer2 → [有序子集2]
[数据] → reducer3 → [有序子集3]
(子集之间无序)
DISTRIBUTE BY: [数据] → 按key分发 → reducer1 (所有key=10)
→ reducer2 (所有key=20)
→ reducer3 (所有key=30)
CLUSTER BY: [数据] → 按key分发 + 内部排序 → reducer1 (key=10, 有序)
→ reducer2 (key=20, 有序)
→ reducer3 (key=30, 有序)
五、HDFS 读写流程
5.1 Hive 查询数据时,底层 HDFS 是怎么工作的?
text
┌─────────────────────────────────────────────────────────────┐
│ 查询流程 │
├─────────────────────────────────────────────────────────────┤
│ 1. 客户端(Hive) 向 NameNode 发送读请求 │
│ 2. NameNode 验证权限,检查文件是否存在 │
│ 3. NameNode 返回文件元数据(文件位置、块信息) │
│ 4. 客户端根据元数据,直接与 DataNode 通信读取数据 │
│ 5. DataNode 返回数据块内容 │
│ 6. Hive 组装数据返回给用户 │
└─────────────────────────────────────────────────────────────┘
简化版流程:Hive → NameNode(获取元数据)→ DataNode(读取数据)→ Hive
5.2 写入流程(插入数据)
text
┌─────────────────────────────────────────────────────────────┐
│ 写入流程 │
├─────────────────────────────────────────────────────────────┤
│ 1. 客户端向 NameNode 请求创建文件 │
│ 2. NameNode 检查权限和空间 │
│ 3. NameNode 返回可用的 DataNode 列表 │
│ 4. 客户端将数据分块写入 DataNode │
│ 5. DataNode 之间复制副本(默认3份) │
│ 6. 写入完成,NameNode 更新元数据 │
└─────────────────────────────────────────────────────────────┘
六、Hive 优化(面试重点)
6.1 优化可以从哪些角度入手?
| 角度 | 负责角色 | 主要内容 |
|---|---|---|
| 运维角度 | 运维工程师 | 管理集群、服务器配置、节点扩展 |
| 模型开发角度 | 数据模型师 | 表结构设计、分区/分桶、存储格式 |
| 数据开发角度 | 数据开发工程师 | SQL 写法、参数调优、代码规范 |
6.2 运维角度优化
| 优化项 | 说明 |
|---|---|
| 参数优化 | JVM 内存配置、动态分区严格模式、笛卡尔积严格模式 |
| 节点扩展 | 增加服务器节点,提升计算能力 |
| 硬件配套 | 更好的 CPU、更大内存、SSD 硬盘 |
6.3 模型开发角度优化
| 优化项 | 说明 |
|---|---|
| 分区/分桶设计 | 合理分区减少扫描量,分桶便于采样 |
| 列式存储 | 数据量大时使用 ORC 格式,压缩比高、查询快 |
| 代理键设计 | 使用 org_id、account_id 等整数类型作为关联键,比字符串快 |
6.4 数据开发角度优化(重点)
| 优化项 | 说明 | 示例 |
|---|---|---|
| 先过滤再关联 | 减少 JOIN 的数据量 | SELECT * FROM a JOIN b ON a.id=b.id WHERE a.date='2024-01-01' 不如先过滤 a 表 |
| 先过滤再分组 | 减少 GROUP BY 的数据量 | 先 WHERE 过滤,再 GROUP BY |
| 慎用全局排序 | ORDER BY 只有一个 reducer,数据量大时极慢 | 能用 SORT BY 就不用 ORDER BY |
| 慎用 DISTINCT | 去重操作消耗大量资源 | 能用 GROUP BY 代替就用 GROUP BY |
| 慎用 UNION | 需要合并去重,开销大 | 确定无重复时用 UNION ALL |
| Map Join | 大表 JOIN 小表时,把小表放入内存 | 小表不能超过内存大小 |
| 避免数据倾斜 | 解决 key 分布不均的问题 | 详见上一章的"数据倾斜"部分 |
| 合理设置参数 | 调整 map/reduce 相关参数 | set hive.map.aggr=true; |
6.5 Map Join 详解
什么是 Map Join?
传统 JOIN 需要经过 shuffle 阶段(Map → Shuffle → Reduce),Map Join 把小表加载到内存,在 Map 阶段直接完成 JOIN,避免 shuffle。
如何使用?
sql
-- 方式1:自动 Map Join(Hive 会自动判断)
set hive.auto.convert.join=true;
set hive.mapjoin.smalltable.filesize=25000000; -- 小表阈值 25MB
-- 方式2:手动指定(Hive 的 map join 语法)
select /*+ mapjoin(a) */ *
from 小表 a
left join 大表 b on a.id = b.id;
七、面试常见问题:大表关联大表跑不过怎么办?
问题场景
两个都是大表(TB 级别),执行 JOIN 时出现内存不足、任务失败。
解决方案汇总
| 方案 | 说明 | 适用场景 |
|---|---|---|
| 调整 JVM 内存 | 增加 reducer 的内存大小 | 内存不够但数据量可控 |
| 拆表关联 | 将一张大表拆成 N 张小表,逐个关联后合并 | 大表可按某个维度拆分 |
| 分桶优化 | 对大表按关联键预先分桶 | 两表按相同键分桶,可避免 shuffle |
| Map Join | 如果大表可以过滤成小表 | 关联前能大幅过滤数据 |
详细方案解释
方案一:调整 JVM 内存
bash
# 修改 hive-site.xml 或执行 set 命令
set mapreduce.map.memory.mb=4096; # map 内存 4GB
set mapreduce.reduce.memory.mb=8192; # reduce 内存 8GB
方案二:拆表关联
sql
-- 将大表 A 按某个维度拆成 N 张小表
-- 例如按部门拆分成 A_dept10, A_dept20, A_dept30
-- 逐个关联
insert into tmp1
select /*+ mapjoin(a) */ *
from A_dept10 a
left join 大表B b on a.id = b.id;
insert into tmp2
select /*+ mapjoin(a) */ *
from A_dept20 a
left join 大表B b on a.id = b.id;
-- 最后合并所有结果
insert into result
select * from tmp1
union all
select * from tmp2
union all
...
方案三:分桶优化
sql
-- 创建分桶表时,让两张表按相同的键分桶,桶数相同
create table A_bucketed (
id int, name string
)
clustered by (id) into 128 buckets;
create table B_bucketed (
id int, name string
)
clustered by (id) into 128 buckets;
-- 分桶后 JOIN,相同 id 的数据已在同一 bucket,避免 shuffle
insert into result
select * from A_bucketed a
join B_bucketed b on a.id = b.id;
方案四:先过滤再关联
sql
-- 如果大表关联前能大幅过滤数据,先用子查询过滤
insert into result
select *
from (select * from 大表A where date = '2024-01-01') a
left join (select * from 大表B where date = '2024-01-01') b
on a.id = b.id;
八、面试常见问题:Hive 优化参数汇总
| 参数 | 作用 | 建议值 |
|---|---|---|
hive.auto.convert.join |
自动 Map Join | true |
hive.mapjoin.smalltable.filesize |
小表阈值 | 25000000(25MB) |
hive.exec.dynamic.partition.mode |
动态分区模式 | nonstrict(允许动态分区) |
hive.exec.dynamic.partition |
是否开启动态分区 | true |
hive.groupby.skewindata |
处理 group by 数据倾斜 | true |
mapreduce.map.memory.mb |
Map 内存 | 根据实际情况调整 |
mapreduce.reduce.memory.mb |
Reduce 内存 | 根据实际情况调整 |
九、命令速查表
| 操作 | 命令 |
|---|---|
| 直接执行 SQL | hive -e "SELECT * FROM table" |
| 执行 SQL 文件 | hive -f script.sql |
| 指定存储格式 | STORED AS orc |
| Map Join 提示 | SELECT /*+ MAPJOIN(small_table) */ ... |
| 设置自动 Map Join | set hive.auto.convert.join=true; |
| 设置动态分区 | set hive.exec.dynamic.partition.mode=nonstrict; |
| 设置 group by 倾斜处理 | set hive.groupby.skewindata=true; |
十、核心概念总结
| 概念 | 一句话总结 |
|---|---|
hive -e |
直接在 Linux 命令行执行 Hive SQL |
hive -f |
执行文件中的 Hive SQL |
| ORC 格式 | 列式存储,压缩比高,适合大数据量 |
| ORDER BY | 全局排序,只有一个 reducer |
| SORT BY | 每个 reducer 内部排序 |
| DISTRIBUTE BY | 按指定字段分发到不同 reducer |
| CLUSTER BY | 分发 + 排序(同一字段) |
| Map Join | 把小表放内存,避免 shuffle |
| 数据倾斜 | key 分布不均导致某些节点负载过高 |