查询数据

Hive 查询:基础 SQL 你会,但 ORDER BY 在大数据量下会卡死,得用 SORT BY + DISTRIBUTE BY

Hive 的查询语法跟 MySQL 差不多,SELECTWHEREGROUP BYJOIN 都一样。

但有一个关键区别: 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 BYSORT 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;