Hive教程:触发 MapReduce 的查询类型

介绍

Hive 底层依赖 MapReduce(或 Tez/Spark)执行分布式计算,并非所有查询都触发 MapReduce:简单的元数据查询(如查表结构)仅访问 Hive Metastore,而涉及 数据扫描、计算、聚合 的查询会触发 MapReduce 任务。

触发 MapReduce 的查询

  1. 需要扫描/处理 HDFS 上的实际数据(而非仅查元数据);
  2. 需要分布式计算(聚合、排序、连接、分组等);
  3. 即使是简单扫描,若开启了 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;

原文出处:/show_1GW2MEg5RUdI.html