查询数据
Hive 查询:基础 SQL 你会,但 ORDER BY 在大数据量下会卡死,得用 SORT BY + DISTRIBUTE BY
Hive 的查询语法跟 MySQL 差不多,SELECT、WHERE、GROUP BY、JOIN 都一样。
但有一个关键区别: Hive 是分布式的,数据散落在多台机器上。ORDER BY 要把所有数据拉到一台机器上排序,数据量大的时候会卡死。
所以 Hive 有一套分布式排序的语法:
| 关键字 | 做什么 | 全局有序吗 |
|---|---|---|
ORDER BY |
全局排序 | 是(但慢) |
SORT BY |
每个 Reducer 内部排序 | 否 |
DISTRIBUTE BY |
控制数据分到哪个 Reducer | — |
CLUSTER BY |
DISTRIBUTE BY + SORT BY(同字段) | 否 |
基础查询:跟 SQL 一样,快速过
这些语法跟 MySQL 没区别,看一眼就行。
| 操作 | SQL |
|---|---|
| 全表查 | SELECT * FROM dept; |
| 查特定列 | SELECT deptno, dname FROM dept; |
| 条件过滤 | SELECT * FROM emp WHERE sal > 2000; |
| 去重 | SELECT DISTINCT deptno FROM emp; |
| 范围 | SELECT * FROM emp WHERE sal BETWEEN 1000 AND 3000; |
| 枚举 | SELECT * FROM emp WHERE deptno IN (10, 20); |
| 模糊 | SELECT * FROM emp WHERE ename LIKE 'A%'; |
| 分组聚合 | SELECT deptno, AVG(sal) FROM emp GROUP BY deptno; |
| 聚合过滤 | SELECT deptno, AVG(sal) FROM emp GROUP BY deptno HAVING AVG(sal) > 2000; |
| JOIN | SELECT * FROM emp e JOIN dept d ON e.deptno = d.deptno; |
| 限制行数 | SELECT * FROM emp LIMIT 10; |
| NULL 判断 | SELECT * FROM emp WHERE sal IS NULL; |
ORDER BY:全局排序,但大数据量会卡死
ORDER BY 保证全局有序,但代价是所有数据都跑到一个 Reducer 上排序。
SELECT ename, sal FROM emp ORDER BY sal DESC;
执行的时候日志里会看到:
number of reducers: 1
数据量小(几百 MB)没问题,数据量大(几十 GB)单个 Reducer 扛不住。 跑十几分钟甚至超时是常事。
什么时候用 ORDER BY:
- 数据量小(结果集 < 1GB)
- 必须全局有序(比如最终报表展示)
SORT BY:每个 Reducer 内部排序,不保证全局
SORT BY 让每个 Reducer 自己排自己的,输出文件内部有序,但文件之间不一定有序。
SELECT ename, deptno, sal
FROM emp
SORT BY sal DESC;
如果有 3 个 Reducer,输出 3 个文件,每个文件内部按 sal DESC 排好了,但文件 1 和文件 2 之间的顺序是不确定的。
执行机制:
- 数据随机分到各个 Reducer
- 每个 Reducer 独立排序
- 不会把所有数据集中到一台机器
什么时候用 SORT BY:
- 数据量大,不需要全局有序
- 每个输出文件内部的顺序有要求(比如按分区导出)
DISTRIBUTE BY:控制数据分到哪个 Reducer
SORT BY 的问题是数据分配是随机的。如果你想”相同部门的数据分到同一个 Reducer,再按薪资排序”,得用 DISTRIBUTE BY。
SELECT deptno, ename, sal
FROM emp
DISTRIBUTE BY deptno -- 相同 deptno 去同一个 Reducer
SORT BY sal DESC; -- 每个 Reducer 内部按薪资排
执行效果:
- 部门 10 的所有数据 → Reducer 1
- 部门 20 的所有数据 → Reducer 2
- 部门 30 的所有数据 → Reducer 3
- 每个 Reducer 内部按
sal DESC排
DISTRIBUTE BY 的分配规则: 对 deptno 取哈希值,再对 Reducer 数量取模。相同值一定去同一个 Reducer。
CLUSTER BY:DISTRIBUTE BY + SORT BY 的简写
如果 DISTRIBUTE BY 和 SORT BY 用的是同一个字段,可以简写成 CLUSTER BY:
-- 这两种写法等价
SELECT deptno, ename FROM emp DISTRIBUTE BY deptno SORT BY deptno;
SELECT deptno, ename FROM emp CLUSTER BY deptno;
限制: CLUSTER BY 只能升序排序,降序得拆开来写:
SELECT deptno, ename FROM emp DISTRIBUTE BY deptno SORT BY deptno DESC;