四个排序子句的区别
Hive 有四个控制排序与数据分发的子句。ORDER BY 保证全局有序,代价是强制只用一个 reducer;SORT BY 只在每个 reducer 内部排序,多个 reducer 的输出文件之间无序;DISTRIBUTE BY 只按列值把数据分发到不同 reducer,本身不排序;CLUSTER BY 等于 DISTRIBUTE BY 加同列升序 SORT BY,是简写形式且不支持降序。理解它们的组合规律就一条:DISTRIBUTE BY 决定数据落到哪个 reducer,SORT BY 决定每个 reducer 内部怎么排。
基本信息
| 适用平台 | Apache Hive(1.x 起支持这四个子句);Spark SQL 中同名子句语义不完全一致,不要照搬 |
|---|---|
| 子句清单 | ORDER BY / SORT BY / DISTRIBUTE BY / CLUSTER BY |
| 全局有序代价 | ORDER BY 固定收敛到 1 个 reducer |
| 分发规则 | DISTRIBUTE BY 按列值哈希决定 reducer,同列值的行必然同 reducer |
| 并行度控制 | reduce 数量由 mapreduce.job.reduces(或 Tez/Spark 执行引擎对应参数)决定 |
| 版本差异 | Hive 1.x/2.x 可用 hive.mapred.mode=strict 禁止不带 LIMIT 的 ORDER BY |
典型使用场景
- 取 TopN:小结果集用 ORDER BY ... LIMIT,优化器会用堆排序只保留前 N 条,不必真的全排
- 按门店做聚合但要求同门店数据落同一 reducer:DISTRIBUTE BY store_id,避免跨 reducer 再合并
- 导出文件希望每个文件内部有序、便于下游归并读取:SORT BY 让每个 reducer 各自排好
- 分发列与排序列相同时用 CLUSTER BY 一行写清,例如 CLUSTER BY dt
- 多 reducer 写出后要保证某个键内全局有序:DISTRIBUTE BY key 再 SORT BY 同键,该键内即为全局有序
四种写法对照
四种写法对照
-- 全局有序,只跑一个 reducer,务必带 LIMIT 控制数据量
SELECT store_id, order_id, pay_amt
FROM dwd_trade_order_di
WHERE dt = '2026-10-12'
ORDER BY pay_amt DESC
LIMIT 100;
-- 按门店分发,每个 reducer 内按金额降序;文件之间无序
SELECT store_id, order_id, pay_amt
FROM dwd_trade_order_di
WHERE dt = '2026-10-12'
DISTRIBUTE BY store_id
SORT BY pay_amt DESC;
-- 等价简写:按 store_id 分发并升序排序
SELECT store_id, order_id FROM dwd_trade_order_di CLUSTER BY store_id;四个子句逐项对照
| 子句 | 有序范围 | reducer 数 | 典型用途 |
|---|---|---|---|
| ORDER BY | 全局有序 | 1 个 | 小结果集最终排序、取 TopN |
| SORT BY | reducer 内部有序 | 多个 | 导出有序文件,避免单点 |
| DISTRIBUTE BY | 不排序,只控制落点 | 多个 | 按业务键分发,保证同键同 reducer |
| CLUSTER BY | reducer 内升序 | 多个 | 分发列与排序列一致的简化写法 |
SORT BY 保证的是每个 reducer 输出文件内部有序,多个文件之间没有任何顺序约定,下游按文件顺序取值会出错。
大表直接 ORDER BY 会把全量数据压到单个 reducer,reduce 阶段长时间停滞甚至 OOM,且失败后整段重跑。