介绍
Hive 底层依赖 MapReduce(或 Tez/Spark)执行分布式计算,并非所有查询都触发 MapReduce:简单的元数据查询(如查表结构)仅访问 Hive Metastore,而涉及 数据扫描、计算、聚合 的查询会触发 MapReduce 任务。
触发 MapReduce 的查询
- 需要扫描/处理 HDFS 上的实际数据(而非仅查元数据);
- 需要分布式计算(聚合、排序、连接、分组等);
- 即使是简单扫描,若开启了
hive.fetch.task.conversion=none(默认是more),简单查询也会触发 MapReduce(下文会讲)。
聚合类查询(GROUP BY / 聚合函数)
所有涉及 GROUP BY、DISTINCT 或聚合函数(SUM/AVG/MAX/MIN/COUNT 等)的查询,必须通过 MapReduce 完成数据分片聚合(Map 端局部聚合 + Reduce 端全局聚合)。
示例
-- 按部门统计薪资总和(触发MapReduce)
SELECT dept, SUM(salary) FROM emp GROUP BY dept;
-- 统计非空薪资的数量(触发MapReduce)
SELECT COUNT(DISTINCT salary) FROM emp;
-- 求部门最高薪资(触发MapReduce)
SELECT dept, MAX(salary) FROM emp GROUP BY dept;
多表关联查询(JOIN)
JOIN(内连接/外连接/交叉连接)需要分布式 shuffle 操作匹配关联键,必然触发 MapReduce(Map 端分发数据,Reduce 端匹配连接)。
示例
-- 员工表关联部门表(触发MapReduce)
SELECT e.empno, e.ename, d.deptname
FROM emp e JOIN dept d ON e.deptno = d.deptno;
-- 左外连接(触发MapReduce)
SELECT e.empno, d.deptname
FROM emp e LEFT JOIN dept d ON e.deptno = d.deptno;
排序/分桶类查询(ORDER BY / SORT BY / CLUSTER BY)
ORDER BY:全局排序,触发单 Reduce 任务的 MapReduce(需全量数据排序);SORT BY/DISTRIBUTE BY/CLUSTER BY:分区排序/分桶,触发 MapReduce(Map 分发,Reduce 排序)。
示例
-- 按薪资全局排序(触发MapReduce)
SELECT * FROM emp ORDER BY salary DESC;
-- 按部门分区,薪资排序(触发MapReduce)
SELECT * FROM emp DISTRIBUTE BY dept SORT BY salary;
数据插入/覆盖(INSERT OVERWRITE/INTO)
向表/分区插入数据(尤其是基于查询结果的插入),需要 MapReduce 处理数据并写入 HDFS。
示例
-- 覆盖插入部门统计结果到新表(触发MapReduce)
INSERT OVERWRITE TABLE emp_dept_sum
SELECT dept, SUM(salary) FROM emp GROUP BY dept;
-- 增量插入分区数据(触发MapReduce)
INSERT INTO TABLE emp PARTITION (dt='202501')
SELECT empno, ename FROM emp WHERE dt='202412';
复杂过滤+计算的查询(含 UDF/窗口函数)
- 窗口函数(
ROW_NUMBER()/RANK()/OVER()):需分布式计算窗口内数据,触发 MapReduce; - 自定义 UDF + 大量数据过滤:需扫描并处理数据,触发 MapReduce;
- 嵌套子查询(需物化中间结果):触发 MapReduce。
示例
-- 窗口函数:按部门排名薪资(触发MapReduce)
SELECT empno, ename, dept, salary,
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rank
FROM emp;
-- 嵌套子查询(触发MapReduce)
SELECT * FROM (
SELECT dept, AVG(salary) AS avg_sal FROM emp GROUP BY dept
) t WHERE avg_sal > 5000;
分桶表相关操作
分桶表的 CLUSTER BY、分桶连接(BUCKET JOIN)、分桶抽样(TABLESAMPLE),均需 MapReduce 处理分桶数据。
示例
-- 分桶表抽样查询(触发MapReduce)
SELECT * FROM emp TABLESAMPLE(BUCKET 1 OUT OF 4 ON deptno);
-- 分桶连接(触发MapReduce)
SELECT e.empno, d.deptname
FROM emp e JOIN dept d ON e.deptno = d.deptno
CLUSTER BY e.deptno;
DDL 中涉及数据处理的操作
部分 DDL 操作需扫描数据,触发 MapReduce:
ALTER TABLE ... REPLACE COLUMNS(需重写数据);ANALYZE TABLE ... COMPUTE STATISTICS(计算表/列的统计信息)。
示例
-- 计算表的统计信息(触发MapReduce)
ANALYZE TABLE emp COMPUTE STATISTICS;
-- 计算列的统计信息(触发MapReduce)
ANALYZE TABLE emp COMPUTE STATISTICS FOR COLUMNS salary;
不会触发 MapReduce 的查询
以下查询仅访问 Hive Metastore(元数据)或通过「Fetch Task」直接读取少量数据,无需 MapReduce:
1. 元数据查询
-- 查表结构(仅查Metastore)
DESC emp;
DESC EXTENDED emp;
-- 查数据库列表(仅查Metastore)
SHOW DATABASES;
SHOW TABLES;
-- 查分区信息(仅查Metastore)
SHOW PARTITIONS emp;
简单全表/行过滤(Fetch Task 优化)
Hive 配置 hive.fetch.task.conversion=more(默认)时,以下查询通过「Fetch Task」直接读取文件,不触发 MapReduce:
SELECT * FROM emp LIMIT 100;(限制少量数据);SELECT empno, ename FROM emp WHERE empno=1001;(单条件过滤,无聚合/排序);SELECT empno FROM emp;(仅查单个字段,无计算)。
注:若将
hive.fetch.task.conversion设为none,上述查询也会触发 MapReduce。
本地模式下的小数据查询
Hive 开启本地模式(hive.exec.mode.local.auto=true)且数据量小于阈值(默认 128MB)时,简单查询会在本地执行(无分布式 MapReduce)。
配置:控制 MapReduce 触发
| 配置项 | 默认值 | 作用 |
|---|---|---|
hive.fetch.task.conversion |
more |
设为 more:简单查询(SELECT/过滤/LIMIT)用 Fetch Task,不触发MR;设为 none:所有查询都触发MR |
hive.exec.mode.local.auto |
true |
自动开启本地模式,小数据查询在本地执行(无分布式MR) |
hive.exec.reducers.bytes.per.reducer |
256000000 |
控制Reduce数量,间接影响MR执行效率 |
总结:是否触发 MapReduce
| 查询特征 | 是否触发MR |
|---|---|
| 仅查元数据(DESC/SHOW) | ❌ |
| 简单SELECT/过滤/LIMIT(Fetch Task) | ❌ |
| 聚合(GROUP BY/聚合函数) | ✅ |
| 关联(JOIN) | ✅ |
| 排序(ORDER BY/SORT BY) | ✅ |
| 插入数据(INSERT OVERWRITE/INTO) | ✅ |
| 窗口函数/分桶操作 | ✅ |
| 统计信息计算(ANALYZE) | ✅ |
生产中可通过 EXPLAIN 命令提前查看执行计划,判断是否触发 MapReduce:
-- 查看执行计划,若包含「MapReduce Operator Tree」则触发MR
EXPLAIN SELECT dept, SUM(salary) FROM emp GROUP BY dept;