Hive 中的窗口函数

Posted

技术标签:

【中文标题】Hive 中的窗口函数【英文标题】:Windowing function in Hive 【发布时间】:2019-04-29 18:34:38 【问题描述】:

我正在探索 ,并且能够理解所有 UDF 的功能。虽然,我无法理解我们与其他函数一起使用的 partition by 和 order by。以下是与我计划构建的查询非常相似的结构。

SELECT a, RANK() OVER(partition by b order by c) as d from xyz; 

只是想了解这两个关键字所涉及的后台进程。

感谢帮助:)

【问题讨论】:

【参考方案1】:

RANK() 分析函数为数据集中每个分区中的每一行分配一个排名。

PARTITION BY 子句确定行的分布方式(如果是 hive,则在 reducer 之间)。

ORDER BY 确定分区中行的排序方式。

第一阶段由分布,数据集中的所有行都分布到分区中。在 map-reduce 中,每个映射器根据partition by 对行进行分组,并为每个分区生成文件。 Mapper 根据order by 对分区部分进行初始排序。

第二阶段,所有行在每个分区内排序。 在map-reduce中,每个reducer获取mapper产生的partitions文件(partitions的一部分),并根据order by对整个partition中的行进行排序(partial results的排序)。

第三,rank函数为分区中的每一行分配rank。正在为每个分区初始化 Rank 函数。

对于分区等级中的第一行以 1 开头。对于每个下一行 Rank=previous row rank+1。具有相同值的行(按顺序指定)给定相同的排名,如果两行共享相同的排名,则下一行排名不连续。

不同的分区可以在不同的reducer上并行处理。小分区可以在同一个reducer上处理。 Rank 函数在跨越分区边界时重新初始化,并从每个分区的 rank=1 开始。

示例(行已在分区内分区和排序):

SELECT a, RANK() OVER(partition by b order by c) as d from xyz; 

a, b, c, d(rank)
----------------
1  1  1  1 --starts with 1
2  1  1  1 --the same c value, the same rank=1
3  1  2  3 --rank 2 is skipped because second row shares the same rank as first 

4  2  3  1 --New partition starts with 1
5  2  4  2
6  2  5  3

如果您需要连续排名,请使用dense_rank 函数。 dense_rank 将为上述数据集中的第三行生成 rank=2。

row_number 函数将为分区中从 1 开始的每一行分配一个位置编号。具有相同值的行将收到不同的连续编号。

SELECT a, ROW_NUMBER() OVER(partition by b order by c) as d from xyz; 

a, b, c, d(row_number)
----------------
1  1  1  1 --starts with 1
2  1  1  2 --the same c value, row number=2
3  1  2  3 --row position=3

4  2  3  1 --New partition starts with 1
5  2  4  2
6  2  5  3

重要提示:对于具有相同值row_number 或其他此类分析函数的行,可能具有不确定的行为,并且每次运行都会产生不同的数字。上述数据集中的第一行可能会收到数字 2,第二行可能会收到数字 1,反之亦然,因为除非您在 order by 子句中再添加一个列 a,否则它们的顺序是不确定的。在这种情况下,从运行到运行,所有行将始终具有相同的 row_number,它们的顺序值是不同的。

【讨论】:

感谢您的详细解释。只是一个小问题,如果表已经被一些键分区和排序怎么办?这适用还是我错过了什么? 表分区通常与分析函数partition by子句没有任何共同之处。同表分区可以提高效率,mapper会处理同一个分区,产生更少的输出文件。在 Codd 的理论中,表格没有按定义排序。由于并行性,只有 order by 保证了顺序。您可以 order 提高打包 ORC 或 Parquet 文件的效率,提高内部索引效率,提高文件压缩,插入期间的 order by 与查询返回的行的 order 没有共同之处。@987654321 @ @satishsilveri 当然,表分区可以提高过滤效率。但是表数据是并行读取的,并且映射器和化简器彼此隔离,不同步,并行独立地发出行。这就是为什么即使数据在表文件中排序,查询的结果也可能没有排序的原因。 Mapper does initial sorting of partitions parts - 在第一阶段,这是否也符合order by中提到的字段? @tuk 是的。 mapper处理的partition部分按照order by排序。

以上是关于Hive 中的窗口函数的主要内容,如果未能解决你的问题,请参考以下文章

Hive中的窗口函数

Hive 中的窗口函数

举一反三-Pandas实现Hive中的窗口函数

Hive之窗口函数

使用窗口函数时,hive 是不是支持 PARTITION BY 语句中的复杂类型?

Hive row_number() 中的自定义排序,按窗口函数排序