排序,排序,聚类和分配

这描述了 SELECT 子句 ORDER BY,SORT BY,CLUSTER BY 和 DISTRIBUTE BY 的语法。有关一般信息,请参见Select Syntax

Order By 的语法

Hive QL 中的* ORDER BY 语法类似于 SQL 语言中的 ORDER BY *语法。

colOrder: ( ASC | DESC )
colNullOrder: (NULLS FIRST | NULLS LAST)           -- (Note: Available in Hive 2.1.0 and later)
orderBy: ORDER BY colName colOrder? colNullOrder? (',' colName colOrder? colNullOrder?)*
query: SELECT expression (',' expression)* FROM src orderBy

“ order by”子句中有一些限制。在严格模式下(即hive.mapred.mode = strict),必须在 order by 子句后跟一个“ limit”子句。如果将 hive.mapred.mode 设置为 nonstrict,则没有 limit 子句。原因是为了强加所有结果的总 Sequences,必须有一个减速器才能对最终输出进行排序。如果输出中的行数太大,则单个减速器可能需要很长时间才能完成。

请注意,列是通过名称而不是位置编号指定的。但是,在Hive 0.11.0及更高版本中,按以下方式配置时可以按位置指定列:

默认排序 Sequences 为升序(ASC)。

Hive 2.1.0及更高版本中,支持为“ order by”子句中的每个列指定空排序 Sequences。 ASCSequences 的默认空排序 Sequences 为 NULLS FIRST,而 DESCSequences 的默认空排序 Sequences 为 NULLS LAST。

Hive 3.0.0及更高版本中,优化器将删除subqueriesviews中的无限制订单。要禁用它,请将hive.remove.orderby.in.subquery设置为 false。

排序依据的语法

  • SORT BY 语法类似于 SQL 语言中的 ORDER BY *语法。
colOrder: ( ASC | DESC )
sortBy: SORT BY colName colOrder? (',' colName colOrder?)*
query: SELECT expression (',' expression)* FROM src sortBy

Hive 使用* SORT BY *中的列对行进行排序,然后再将行 Importing 到 reducer。排序 Sequences 将取决于列类型。如果列是数字类型,则排序 Sequences 也是数字 Sequences。如果列是字符串类型,则排序 Sequences 将是字典 Sequences。

Hive 3.0.0及更高版本中,优化器将删除subqueriesviews中的无限制排序。要禁用它,请将hive.remove.orderby.in.subquery设置为 false。

排序依据和排序依据之间的差异

Hive 支持* SORT BY *,可对每个 reducer 的数据进行排序。 “ order by”和“ sort by”之间的区别在于,前者保证输出中的总 Sequences,而后者仅保证精简器中行的排序。如果存在多个减速器,则“排序依据”可能会给出部分排序的最终结果。

注意:关于单个列的单独 SORT BY 与 CLUSTER BY 之间的区别可能会造成混淆。不同之处在于,如果有多个 reducer 分区,则 CLUSTER BY 按字段划分,而 SORT BY 则是随机划分,以便在 reducer 上均匀地分布数据(和负载)。

基本上,每个 reducer 中的数据将根据用户指定的 Sequences 进行排序。以下示例显示

SELECT key, value FROM src SORT BY key ASC, value DESC

该查询有 2 个 reducer,每个的输出为:

0   5
0   3
3   6
9   1
0   4
0   3
1   1
2   5

设置排序依据的类型

转换后,通常将变量类型视为字符串,这意味着将按字典 Sequences 对数字数据进行排序。为了克服这个问题,可以在使用 SORT BY 之前使用第二个带有强制类型转换的 SELECT 语句。

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 *主要与Transform/Map-Reduce Scripts一起使用。但是,如果需要对查询的输出进行分区和排序以用于后续查询,有时在 SELECT 语句中很有用。

  • Cluster By Distribute By Sort By *的快捷方式。

Hive 使用* Distribute By 中的列在减速器之间分配行。具有相同 Distribute By 列的所有行将进入相同的 reducer。但是, Distribute By *不保证分布式键上的聚类或排序属性。

例如,我们将以下 5 行的* x 分配给 2 个 reducer:

x1
x2
x4
x3
x1

减速机 1

x1
x2
x1

减速机 2

x4
x3

请注意,具有相同键 x1 的所有行都可以保证分配给同一归约器(在这种情况下为归约器 1),但不能保证它们聚集在相邻位置。

相反,如果我们使用* Cluster By x *,则两个化简器将进一步对 x 上的行进行排序:

减速机 1

x1
x1
x2

减速机 2

x3
x4

用户可以指定* Distribute By Sort By 来代替 Cluster By *,因此分区列和排序列可以不同。通常的情况是分区列是排序列的前缀,但这不是必需的。

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 'reduce_script'
    AS date, count;