Hive中主要有四个用于排序的关键字,它们各有特点,适用于不同的场景。
核心区别总结如下表,之后会进行详细解释:
| 特性 | ORDER BY | SORT BY | DISTRIBUTE BY | CLUSTER BY |
|---|---|---|---|---|
| 全局/局部排序 | 全局排序 | 局部排序(Reducer内) | 仅分区,不排序 | 局部排序(分区内且排序) |
| Reducer数量 | 1个 | 多个 | 多个 | 多个 |
| 输出文件数 | 1个 | 多个 | 多个 | 多个 |
| 功能描述 | 对所有数据进行整体排序,保证全局有序 | 在每个Reducer内部进行排序 | 按照指定字段分区,控制数据分发 | DISTRIBUTE BY + SORT BY 的简写 |
| 性能 | 差(数据倾斜和单点压力风险) | 好 | - | 好 |
| 使用场景 | 需要最终全局有序结果的场景 | 大规模数据并行排序,不要求全局有序 | 为后续的聚合或排序做数据分区准备 | 既想分区,又希望分区内有序 |
详细说明与区别
1. ORDER BY
- 功能:全局排序。它会将所有数据汇集到一个Reducer中进行排序,最终保证输出文件中的数据是全局有序的。
- 特点:
- 因为只有一个Reducer处理所有数据,所以当数据量非常大时,容易成为性能瓶颈,运行速度很慢。
- 可能会因为数据量过大而导致Reducer内存溢出(OOM)。
- 使用场景:当数据量不大,或者你必须要一个完全有序的最终结果时(例如,查询排行榜Top 10)。
- 示例:
-- 查询员工工资并从高到低全局排序 SELECT name, salary FROM employee ORDER BY salary DESC; -- 结果只有一个文件,里面所有数据按salary降序排列
2. SORT BY
- 功能:局部排序。它在每个Reducer内部对数据进行排序。也就是说,每个Reducer输出的文件自身是有序的,但多个Reducer输出的文件之间是无序的。
- 特点:
- 在多个Reducer上并行执行,性能远高于
ORDER BY。 - 排序的范围受
DISTRIBUTE BY的影响。如果没用DISTRIBUTE BY,Hive会随机分发数据到Reducer。
- 在多个Reducer上并行执行,性能远高于
- 使用场景:处理大规模数据集,且不要求全局结果有序,只要求每个输出文件有序(例如,为后续的归并排序做准备)。
- 示例:
-- 设置Reducer数量为2 SET mapreduce.job.reduces = 2; -- 每个Reducer会处理一部分数据,并在内部按salary排序 SELECT name, salary FROM employee SORT BY salary DESC; -- 结果可能有两个文件: -- File1: (Alice, 100), (Bob, 90) -> 有序 -- File2: (David, 120), (Cathy, 110) -> 有序 -- 但File2的第一行工资(120)比File1的最后一行(100)高,所以全局是无序的。
3. DISTRIBUTE BY
- 功能:控制分区。它负责将Map端输出的数据,按照指定的字段分发到不同的Reducer中。它不保证每个Reducer内部的数据是否排序。
- 特点:
- 类似于MapReduce中的
Partitioner,决定了数据由哪个Reducer处理。 - 通常与
SORT BY结合使用,实现“先按字段A分区,再在分区内按字段B排序”。
- 类似于MapReduce中的
- 使用场景:当需要将相同key的记录发送到同一个Reducer进行处理时(例如,根据部门ID分区,然后对每个部门的员工进行排序)。
- 示例:
SET mapreduce.job.reduces = 2; -- 根据部门id分发数据到Reducer,然后在每个Reducer内按工资排序 SELECT name, dept_id, salary FROM employee DISTRIBUTE BY dept_id SORT BY salary DESC; -- 相同dept_id的员工会被分配到同一个Reducer -- 然后在每个Reducer内部,这些员工再按工资降序排列
4. CLUSTER BY
- 功能:分区并排序。它是
DISTRIBUTE BY和SORT BY的简写形式。当DISTRIBUTE BY的字段和SORT BY的字段相同时,就可以直接用CLUSTER BY替代。 - 特点:
CLUSTER BY col等价于DISTRIBUTE BY col SORT BY col。- 它既负责按字段分区,又负责在分区内按同一个字段排序。注意:排序只能是升序(ASC),不能指定降序(DESC)。
- 使用场景:分区和排序的字段是同一个,且只需要默认升序时。
- 示例:
-- 以下两条语句是等价的 SELECT name, dept_id FROM employee CLUSTER BY dept_id; SELECT name, dept_id FROM employee DISTRIBUTE BY dept_id SORT BY dept_id; -- CLUSTER BY 默认是升序
总结与选择建议
- 要全局有序 -> 用
ORDER BY(数据量小的时候)。 - 要局部有序,且分区和排序字段不同 -> 用
DISTRIBUTE BY ... SORT BY ...。 - 要局部有序,且分区和排序字段相同 -> 用
CLUSTER BY(注意只能是升序)。 - 只需要局部有序,不关心如何分区 -> 用
SORT BY(让Hive随机分区)。
理解这些区别的关键在于深入理解Hive和MapReduce的工作原理:数据如何从Map端发出,如何通过Partitioner分发到不同的Reducer,以及最终如何输出。

912

被折叠的 条评论
为什么被折叠?



