Hive 中 Order By、Sort By、Cluster By 和 Distribute By 的详细解析

Hive 中 Order By、Sort By、Cluster By 和 Distribute By 的详细解析

在 Hive 数据查询与处理操作中,Order BySort ByCluster ByDistribute By 这些语句对于数据的排序、分区以及在 Reduce 阶段的处理起着关键作用。本文将详细解析它们各自的语法、区别以及一些使用要点,帮助大家深入理解并正确运用这些功能。

一、Order By 语法

Hive QL 中的 ORDER BY 语法与 SQL 语言中的 ORDER BY 语法相似。

(一)语法组成

sql 复制代码
colOrder: ( ASC | DESC )
colNullOrder: (NULLS FIRST | NULLS LAST)           -- (注意:在 Hive 2.1.0 及之后版本可用)
orderBy: ORDER BY colName colOrder? colNullOrder? (',' colName colOrder? colNullOrder?)*
query: SELECT expression (',' expression)* FROM src orderBy

(二)使用限制与注意事项

  1. 在严格模式(即 hive.mapred.mode=strict)下,ORDER BY 子句后面必须跟 LIMIT 子句;若将 hive.mapred.mode 设置为非严格模式,则不需要 LIMIT 子句。这是因为要对所有结果施加全局排序,就需要一个 Reducer 来对最终输出进行排序,如果输出的行数过多,单个 Reducer 可能会花费很长时间来完成排序工作。
  2. 通常是按列名指定列进行排序,不过在 Hive 0.11.0 及之后版本,若进行如下配置,则可以按位置指定列:
    • 对于 Hive 0.11.0 到 2.1.x 版本,设置 hive.groupby.orderby.position.aliastrue(默认值为 false)。
    • 对于 Hive 2.2.0 及之后版本,hive.orderby.position.alias 默认值为 true
  3. 默认的排序顺序是升序(ASC)。在 Hive 2.1.0 及之后版本,支持为 ORDER BY 子句中的每个列指定空值排序顺序,升序(ASC)时默认空值排序顺序为 NULLS FIRST,降序(DESC)时默认空值排序顺序为 NULLS LAST
  4. 在 Hive 3.0.0 及之后版本,子查询和视图中不带 LIMITORDER BY 语句会被优化器移除,若要禁用此功能,可设置 hive.remove.orderby.in.subqueryfalse

二、Sort By 语法

SORT BY 语法同样与 SQL 语言中的 ORDER BY 语法类似,其语法如下:

sql 复制代码
colOrder: ( ASC | DESC )
sortBy: SORT BY colName colOrder? (',' colName colOrder?)*
query: SELECT expression (',' expression)* FROM src sortBy

Hive 会依据 SORT BY 中指定的列在将数据行发送给 Reducer 之前对其进行排序,排序顺序取决于列的数据类型。如果列是数值类型,则按数值顺序排序;若是字符串类型,则按字典序排序。另外,在 Hive 3.0.0 及之后版本,子查询和视图中不带 LIMITSORT BY 语句会被优化器移除,同样可通过设置 hive.remove.orderby.in.subqueryfalse 来禁用此移除操作。

三、Sort By 和 Order By 的区别

Hive 支持 SORT BY 对每个 Reducer 内的数据进行排序,而 ORDER BYSORT BY 的区别在于:前者保证输出结果的全局有序性,后者仅保证在每个 Reducer 内数据行的有序性。如果存在多个 Reducer,使用 SORT BY 可能会得到部分有序的最终结果。

需要注意的是,单独的单列 SORT BYCLUSTER BY 之间的区别可能容易混淆。区别在于 CLUSTER BY 是依据字段进行分区,而 SORT BY 在有多个 Reducer 时会随机分区以便在各个 Reducer 间均匀分配数据(和负载)。例如:

sql 复制代码
SELECT key, value FROM src SORT BY key ASC, value DESC

假设有 2 个 Reducer,每个 Reducer 的输出可能是如下这样部分有序的情况:

复制代码
0   5
0   3
3   6
9   1
0   4
0   3
1   1
2   5

四、Sort By 的类型设置

在进行数据转换后,变量类型通常会被视为字符串,这意味着数值数据将按字典序排序。为解决这个问题,可以在使用 SORT BY 之前使用带有类型转换(cast)的第二个 SELECT 语句,示例如下:

sql 复制代码
FROM (FROM (FROM src
            SELECT TRANSFORM(value)
            USING 'mapper'
            AS value, count) mapped
      SELECT cast(value as double) AS value, cast(count as int) AS count
      SORT BY value, count) sorted
SELECT TRANSFORM(value, count)
USING 'reducer'
AS whatever

五、Cluster By 和 Distribute By 语法

Cluster ByDistribute By 主要在转换/Map - Reduce 脚本中使用,但在某些情况下,如果需要对查询输出进行分区和排序以供后续查询使用,在 SELECT 语句中也很有用。

(一)Cluster By

Cluster ByDistribute BySORT BY 的快捷方式,它会根据指定列同时进行数据的分区和排序操作。

(二)Distribute By

Hive 使用 Distribute By 中的列将数据行分配到各个 Reducer 中,所有具有相同 Distribute By 列值的行都会被分配到同一个 Reducer,但 Distribute By 并不保证对分配的键具有聚类或排序属性。例如,对以下 5 行数据基于 x 进行 Distribute By 分配到 2 个 Reducer 中:

复制代码
x1
x2
x4
x3
x1

则可能出现如下分配情况:

Reducer 1 得到:

复制代码
x1
x2
x1

Reducer 2 得到:

复制代码
x4
x3

可以看到,虽然能保证相同键 x1 的行被分配到同一个 Reducer(此处为 Reducer 1),但并不能保证它们在 Reducer 内是相邻聚集的。

而如果使用 Cluster By x,两个 Reducer 会进一步依据 x 对行进行排序,例如:

Reducer 1 得到:

复制代码
x1
x1
x2

Reducer 2 得到:

复制代码
x3
x4

用户也可以分别指定 Distribute BySORT BY,此时分区列和排序列可以不同,通常情况下分区列是排序列的前缀,但这并非强制要求,示例如下:

sql 复制代码
SELECT col1, col2 FROM t1 CLUSTER BY col1
SELECT col1, col2 FROM t1 DISTRIBUTE BY col1

SELECT col1, col2 FROM t1 DISTRIBUTE BY col1 SORT BY col1 ASC, col2 DESC
FROM (
  FROM pv_users
  MAP ( pv_users.userid, pv_users.date )
  USING 'map_script'
  AS c1, c2, c3
  DISTRIBUTE BY c2
  SORT BY c2, c1) map_output
INSERT OVERWRITE TABLE pv_users_reduced
  REDUCE ( map_output.c1, map_output.c2, map_output.c3 )
  USING 'reducer'
  AS date, count;
相关推荐
winner888119 分钟前
Hive SQL 精进系列:REGEXP_COUNT 函数的用法
hive·sql
winner888120 分钟前
Hive SQL 精进系列:一行变多行的 LATERAL VIEW EXPLODE
hive·hadoop·sql
RestCloud1 小时前
ETL与ELT核心技术解析:如何选择最优数据集成方案
数据仓库·etl·数字化转型·数据集成工具·elt
Jim-2ha05 小时前
How Spark Read Sftp Files from Hadoop SFTP FileSystem
大数据·hadoop·spark
人类群星闪耀时14 小时前
数据分析入门:从数据探索到洞察真相
大数据·hadoop·sql
risc12345614 小时前
export HADOOP_CLASSPATH=`hadoop classpath`
hadoop
weixin_307779131 天前
Visual Studio 2022和C++实现带多组标签的Snowflake SQL查询批量数据导出程序
开发语言·c++·数据仓库·sql·云计算
卡卡东~1 天前
CentOS7 服务器安装 Hadoop 和 Hive
服务器·hive·hadoop
别惊鹊1 天前
hadoop集群配置-ssh无密登陆
服务器·hadoop·ssh
精神病不行计算机不上班2 天前
【数据仓库与数据挖掘基础】第二章 数据仓库原理
数据仓库·数据挖掘·spark