Hive教程:触发 MapReduce 的查询类型 作者:马育民 • 2025-12-06 16:44 • 阅读:10001 # 介绍 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 端全局聚合)。 #### 示例 ```hiveql -- 按部门统计薪资总和(触发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 端匹配连接)。 #### 示例 ```hiveql -- 员工表关联部门表(触发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 排序)。 #### 示例 ```hiveql -- 按薪资全局排序(触发MapReduce) SELECT * FROM emp ORDER BY salary DESC; -- 按部门分区,薪资排序(触发MapReduce) SELECT * FROM emp DISTRIBUTE BY dept SORT BY salary; ``` ### 数据插入/覆盖(INSERT OVERWRITE/INTO) 向表/分区插入数据(尤其是基于查询结果的插入),需要 MapReduce 处理数据并写入 HDFS。 #### 示例 ```hiveql -- 覆盖插入部门统计结果到新表(触发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。 #### 示例 ```hiveql -- 窗口函数:按部门排名薪资(触发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 处理分桶数据。 #### 示例 ```hiveql -- 分桶表抽样查询(触发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`(计算表/列的统计信息)。 #### 示例 ```hiveql -- 计算表的统计信息(触发MapReduce) ANALYZE TABLE emp COMPUTE STATISTICS; -- 计算列的统计信息(触发MapReduce) ANALYZE TABLE emp COMPUTE STATISTICS FOR COLUMNS salary; ``` # 不会触发 MapReduce 的查询 以下查询仅访问 Hive Metastore(元数据)或通过「Fetch Task」直接读取少量数据,无需 MapReduce: ### 1. 元数据查询 ```hiveql -- 查表结构(仅查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: ```hiveql -- 查看执行计划,若包含「MapReduce Operator Tree」则触发MR EXPLAIN SELECT dept, SUM(salary) FROM emp GROUP BY dept; ``` 原文出处:http://malaoshi.top/show_1GW2MEg5RUdI.html